summaryrefslogtreecommitdiffstats
path: root/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
diff options
context:
space:
mode:
authorHyunyoung Song <hyunyoungs@google.com>2016-06-15 12:51:30 -0700
committerHyunyoung Song <hyunyoungs@google.com>2016-06-15 12:51:30 -0700
commit7d2fc8120e549eaa9542b0985aab67d172cbd682 (patch)
tree92335d428aa9379039c061bae93188c0b24135a8 /src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
parentb25b2c41c2fa277e16d708ad827e283efcb86452 (diff)
downloadandroid_packages_apps_Trebuchet-7d2fc8120e549eaa9542b0985aab67d172cbd682.tar.gz
android_packages_apps_Trebuchet-7d2fc8120e549eaa9542b0985aab67d172cbd682.tar.bz2
android_packages_apps_Trebuchet-7d2fc8120e549eaa9542b0985aab67d172cbd682.zip
Add caret shaped all app pull up handle to page indicator.
b/28917826 > PageIndicator is also added in landscape > Touch delegate allows the active touch area to be 36dp Change-Id: If00f45fc88a13cd5a6759d771313439eb58561e3
Diffstat (limited to 'src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java')
-rw-r--r--src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java287
1 files changed, 287 insertions, 0 deletions
diff --git a/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java b/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
new file mode 100644
index 000000000..7394426a4
--- /dev/null
+++ b/src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java
@@ -0,0 +1,287 @@
+package com.android.launcher3.pageindicators;
+
+import android.animation.Animator;
+import android.animation.AnimatorListenerAdapter;
+import android.animation.ObjectAnimator;
+import android.animation.ValueAnimator;
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.os.Handler;
+import android.os.Looper;
+import android.support.v4.graphics.ColorUtils;
+import android.util.AttributeSet;
+import android.util.Log;
+import android.util.Property;
+import android.view.TouchDelegate;
+import android.view.View;
+import android.view.ViewConfiguration;
+
+import com.android.launcher3.Launcher;
+import com.android.launcher3.R;
+import com.android.launcher3.Utilities;
+import com.android.launcher3.dynamicui.ExtractedColors;
+
+/**
+ * A PageIndicator that briefly shows a fraction of a line when moving between pages.
+ *
+ * The fraction is 1 / number of pages and the position is based on the progress of the page scroll.
+ */
+public class PageIndicatorLineCaret extends PageIndicator {
+ private static final String TAG = "PageIndicatorLine";
+
+ private static final int[] sTempCoords = new int[2];
+
+ private static final int LINE_ANIMATE_DURATION = ViewConfiguration.getScrollBarFadeDuration();
+ private static final int LINE_FADE_DELAY = ViewConfiguration.getScrollDefaultDelay();
+ public static final int WHITE_ALPHA = (int) (0.70f * 255);
+ public static final int BLACK_ALPHA = (int) (0.65f * 255);
+
+ private static final int LINE_ALPHA_ANIMATOR_INDEX = 0;
+ private static final int NUM_PAGES_ANIMATOR_INDEX = 1;
+ private static final int TOTAL_SCROLL_ANIMATOR_INDEX = 2;
+
+ private ValueAnimator[] mAnimators = new ValueAnimator[3];
+
+ private final Handler mDelayedLineFadeHandler = new Handler(Looper.getMainLooper());
+
+ private boolean mShouldAutoHide = true;
+
+ // The alpha of the line when it is showing.
+ private int mActiveAlpha = 0;
+ // The alpha that the line is being animated to or already at (either 0 or mActiveAlpha).
+ private int mToAlpha;
+ // A float value representing the number of pages, to allow for an animation when it changes.
+ private float mNumPagesFloat;
+ private int mCurrentScroll;
+ private int mTotalScroll;
+ private Paint mLinePaint;
+ private Launcher mLauncher;
+ // all apps pull up handle drawable.
+ private final Drawable caretDrawable;
+ private final int mLineHeight;
+ private final Rect mTouchHitRect = new Rect();
+ private final int mTouchExtensionHeight;
+
+ private static final Property<PageIndicatorLineCaret, Integer> PAINT_ALPHA
+ = new Property<PageIndicatorLineCaret, Integer>(Integer.class, "paint_alpha") {
+ @Override
+ public Integer get(PageIndicatorLineCaret obj) {
+ return obj.mLinePaint.getAlpha();
+ }
+
+ @Override
+ public void set(PageIndicatorLineCaret obj, Integer alpha) {
+ obj.mLinePaint.setAlpha(alpha);
+ obj.invalidate();
+ }
+ };
+
+ private static final Property<PageIndicatorLineCaret, Float> NUM_PAGES
+ = new Property<PageIndicatorLineCaret, Float>(Float.class, "num_pages") {
+ @Override
+ public Float get(PageIndicatorLineCaret obj) {
+ return obj.mNumPagesFloat;
+ }
+
+ @Override
+ public void set(PageIndicatorLineCaret obj, Float numPages) {
+ obj.mNumPagesFloat = numPages;
+ obj.invalidate();
+ }
+ };
+
+ private static final Property<PageIndicatorLineCaret, Integer> TOTAL_SCROLL
+ = new Property<PageIndicatorLineCaret, Integer>(Integer.class, "total_scroll") {
+ @Override
+ public Integer get(PageIndicatorLineCaret obj) {
+ return obj.mTotalScroll;
+ }
+
+ @Override
+ public void set(PageIndicatorLineCaret obj, Integer totalScroll) {
+ obj.mTotalScroll = totalScroll;
+ obj.invalidate();
+ }
+ };
+
+ private Runnable mHideLineRunnable = new Runnable() {
+ @Override
+ public void run() {
+ animateLineToAlpha(0);
+ }
+ };
+
+ public PageIndicatorLineCaret(Context context) {
+ this(context, null);
+ }
+
+ public PageIndicatorLineCaret(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public PageIndicatorLineCaret(Context context, AttributeSet attrs, int defStyle) {
+ super(context, attrs, defStyle);
+ mLinePaint = new Paint();
+ mLinePaint.setAlpha(0);
+
+ mLauncher = (Launcher) context;
+ setOnTouchListener(mLauncher.getHapticFeedbackTouchListener());
+ setOnClickListener(mLauncher);
+ setOnFocusChangeListener(mLauncher.mFocusHandler);
+ Resources res = context.getResources();
+ caretDrawable = res.getDrawable(R.drawable.ic_allapps_caret);
+ mLineHeight = res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_line_height);
+ mTouchExtensionHeight = res.getDimensionPixelSize(
+ R.dimen.dynamic_grid_page_indicator_extra_touch_height);
+ }
+
+ @Override
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+ super.onLayout(changed, left, top, right, bottom);
+ int size = bottom - top;
+ int l = (right - left) / 2 - size / 2;
+ caretDrawable.setBounds(l, 0, l+ size, size);
+
+ // The touch area is expanded below this view by #mTouchExtensionHeight
+ // which extends to the top of the hotseat.
+ View parent = mLauncher.getDragLayer();
+ sTempCoords[0] = sTempCoords[1] = 0;
+ Utilities.getDescendantCoordRelativeToParent(this, parent, sTempCoords, true);
+ mTouchHitRect.set(sTempCoords[0], sTempCoords[1], sTempCoords[0] + this.getWidth(),
+ sTempCoords[1] + getHeight() + mTouchExtensionHeight);
+ parent.setTouchDelegate(new TouchDelegate(mTouchHitRect, this));
+ }
+
+ @Override
+ protected void onDraw(Canvas canvas) {
+ caretDrawable.draw(canvas);
+ if (mTotalScroll == 0 || mNumPagesFloat == 0) {
+ return;
+ }
+
+ // Compute and draw line rect.
+ float progress = Utilities.boundToRange(((float) mCurrentScroll) / mTotalScroll, 0f, 1f);
+ int availableWidth = canvas.getWidth();
+ int lineWidth = (int) (availableWidth / mNumPagesFloat);
+ int lineLeft = (int) (progress * (availableWidth - lineWidth));
+ int lineRight = lineLeft + lineWidth;
+ canvas.drawRect(lineLeft, canvas.getHeight() + mLineHeight, lineRight, canvas.getHeight(),
+ mLinePaint);
+ }
+
+ @Override
+ public void setScroll(int currentScroll, int totalScroll) {
+ if (getAlpha() == 0) {
+ return;
+ }
+ animateLineToAlpha(mActiveAlpha);
+
+ mCurrentScroll = currentScroll;
+ if (mTotalScroll == 0) {
+ mTotalScroll = totalScroll;
+ } else if (mTotalScroll != totalScroll) {
+ animateToTotalScroll(totalScroll);
+ } else {
+ invalidate();
+ }
+
+ if (mShouldAutoHide) {
+ hideAfterDelay();
+ }
+ }
+
+ private void hideAfterDelay() {
+ mDelayedLineFadeHandler.removeCallbacksAndMessages(null);
+ mDelayedLineFadeHandler.postDelayed(mHideLineRunnable, LINE_FADE_DELAY);
+ }
+
+ @Override
+ public void setActiveMarker(int activePage) {
+ }
+
+ @Override
+ protected void onPageCountChanged() {
+ if (Float.compare(mNumPages, mNumPagesFloat) != 0) {
+ animateToNumPages(mNumPages);
+ }
+ }
+
+ public void setShouldAutoHide(boolean shouldAutoHide) {
+ mShouldAutoHide = shouldAutoHide;
+ if (shouldAutoHide && mLinePaint.getAlpha() > 0) {
+ hideAfterDelay();
+ } else if (!shouldAutoHide) {
+ mDelayedLineFadeHandler.removeCallbacksAndMessages(null);
+ }
+ }
+
+ /**
+ * The line's color will be:
+ * - mostly opaque white if the hotseat is white (ignoring alpha)
+ * - mostly opaque black if the hotseat is black (ignoring alpha)
+ */
+ public void updateColor(ExtractedColors extractedColors) {
+ int originalLineAlpha = mLinePaint.getAlpha();
+ int color = extractedColors.getColor(ExtractedColors.HOTSEAT_INDEX, Color.TRANSPARENT);
+ if (color != Color.TRANSPARENT) {
+ color = ColorUtils.setAlphaComponent(color, 255);
+ if (color == Color.BLACK) {
+ mActiveAlpha = BLACK_ALPHA;
+ } else if (color == Color.WHITE) {
+ mActiveAlpha = WHITE_ALPHA;
+ } else {
+ Log.e(TAG, "Setting workspace page indicators to an unsupported color: #"
+ + Integer.toHexString(color));
+ }
+ mLinePaint.setColor(color);
+ mLinePaint.setAlpha(originalLineAlpha);
+ }
+ }
+
+ private void animateLineToAlpha(int alpha) {
+ if (alpha == mToAlpha) {
+ // Ignore the new animation if it is going to the same alpha as the current animation.
+ return;
+ }
+ mToAlpha = alpha;
+ setupAndRunAnimation(ObjectAnimator.ofInt(this, PAINT_ALPHA, alpha),
+ LINE_ALPHA_ANIMATOR_INDEX);
+ }
+
+ private void animateToNumPages(int numPages) {
+ setupAndRunAnimation(ObjectAnimator.ofFloat(this, NUM_PAGES, numPages),
+ NUM_PAGES_ANIMATOR_INDEX);
+ }
+
+ private void animateToTotalScroll(int totalScroll) {
+ setupAndRunAnimation(ObjectAnimator.ofInt(this, TOTAL_SCROLL, totalScroll),
+ TOTAL_SCROLL_ANIMATOR_INDEX);
+ }
+
+ /**
+ * Starts the given animator and stores it in the provided index in {@link #mAnimators} until
+ * the animation ends.
+ *
+ * If an animator is already at the index (i.e. it is already playing), it is canceled and
+ * replaced with the new animator.
+ */
+ private void setupAndRunAnimation(ValueAnimator animator, final int animatorIndex) {
+ if (mAnimators[animatorIndex] != null) {
+ mAnimators[animatorIndex].cancel();
+ }
+ mAnimators[animatorIndex] = animator;
+ mAnimators[animatorIndex].addListener(new AnimatorListenerAdapter() {
+ @Override
+ public void onAnimationEnd(Animator animation) {
+ mAnimators[animatorIndex] = null;
+ }
+ });
+ mAnimators[animatorIndex].setDuration(LINE_ANIMATE_DURATION);
+ mAnimators[animatorIndex].start();
+ }
+}