OSDN Git Service

Adding stateful caret drawable
authorPeter Schiller <peterschiller@google.com>
Wed, 13 Jul 2016 21:04:13 +0000 (14:04 -0700)
committerPeter Schiller <peterschiller@google.com>
Fri, 15 Jul 2016 00:22:49 +0000 (17:22 -0700)
Change-Id: Iba30da09f882297f789c405f932fef10617bba89

12 files changed:
res/drawable/ic_allapps_caret.xml [deleted file]
res/interpolator/caret_animation_interpolator.xml [new file with mode: 0644]
res/values/colors.xml
res/values/config.xml
res/values/dimens.xml
src/com/android/launcher3/LauncherStateTransitionAnimation.java
src/com/android/launcher3/Workspace.java
src/com/android/launcher3/allapps/AllAppsTransitionController.java
src/com/android/launcher3/pageindicators/CaretDrawable.java [new file with mode: 0644]
src/com/android/launcher3/pageindicators/PageIndicator.java
src/com/android/launcher3/pageindicators/PageIndicatorCaretLandscape.java
src/com/android/launcher3/pageindicators/PageIndicatorLineCaret.java

diff --git a/res/drawable/ic_allapps_caret.xml b/res/drawable/ic_allapps_caret.xml
deleted file mode 100644 (file)
index 34d1882..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     Copyright (C) 2016 The Android Open Source Project
-
-     Licensed under the Apache License, Version 2.0 (the "License");
-     you may not use this file except in compliance with the License.
-     You may obtain a copy of the License at
-
-          http://www.apache.org/licenses/LICENSE-2.0
-
-     Unless required by applicable law or agreed to in writing, software
-     distributed under the License is distributed on an "AS IS" BASIS,
-     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-     See the License for the specific language governing permissions and
-     limitations under the License.
--->
-<vector
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:height="24dp"
-    android:viewportHeight="48.0"
-    android:viewportWidth="48.0"
-    android:width="24dp" >
-    <path
-        android:fillColor="#FFFFFF"
-        android:pathData="M14.83,30.83L24,21.66l9.17,9.17L36,28 24,16 12,28z"/>
-</vector>
diff --git a/res/interpolator/caret_animation_interpolator.xml b/res/interpolator/caret_animation_interpolator.xml
new file mode 100644 (file)
index 0000000..25af4bc
--- /dev/null
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="utf-8"?>
+<pathInterpolator
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:pathData="M 0.0,0.0 c 0.0001,0.0 0.0,1.0 1.0,1.0" />
index 937b2f0..dccc53e 100644 (file)
@@ -36,6 +36,7 @@
 
     <color name="outline_color">#FFFFFFFF</color>
     <color name="all_apps_divider_color">#1E000000</color>
+    <color name="all_apps_caret_color">#FFFFFFFF</color>
 
     <color name="spring_loaded_panel_color">#40FFFFFF</color>
     <color name="spring_loaded_highlighted_panel_border_color">#FFF</color>
index 47bfa30..a678958 100644 (file)
@@ -57,6 +57,9 @@
     <!-- The distance at which the animation should take the max duration -->
     <integer name="config_dropAnimMaxDist">800</integer>
 
+    <!-- The duration of the caret animation -->
+    <integer name="config_caretAnimationDuration">200</integer>
+
 <!-- Hotseat -->
     <bool name="hotseat_transpose_layout_with_orientation">true</bool>
 
index 1775d09..38775f1 100644 (file)
@@ -58,7 +58,7 @@
     <dimen name="container_min_margin">8dp</dimen>
     <dimen name="container_max_width">0dp</dimen>
 
-    <!-- All Apps -->
+<!-- All Apps -->
     <dimen name="all_apps_button_scale_down">0dp</dimen>
     <dimen name="all_apps_grid_view_start_margin">0dp</dimen>
     <dimen name="all_apps_grid_section_y_offset">8dp</dimen>
     <dimen name="all_apps_empty_search_bg_top_offset">144dp</dimen>
     <dimen name="all_apps_background_canvas_width">700dp</dimen>
     <dimen name="all_apps_background_canvas_height">475dp</dimen>
+    <dimen name="all_apps_caret_stroke_width">2dp</dimen>
+    <dimen name="all_apps_caret_inset">8dp</dimen>
 
-    <!-- Search bar in All Apps -->
+<!-- Search bar in All Apps -->
     <dimen name="all_apps_header_max_elevation">3dp</dimen>
     <dimen name="all_apps_header_scroll_to_elevation">16dp</dimen>
     <dimen name="all_apps_header_shadow_height">6dp</dimen>
index 6843d60..41b81a9 100644 (file)
@@ -677,7 +677,7 @@ public class LauncherStateTransitionAnimation {
         if (!animated || !initialized) {
             if (FeatureFlags.LAUNCHER3_ALL_APPS_PULL_UP &&
                     fromWorkspaceState == Workspace.State.NORMAL_HIDDEN) {
-                mAllAppsController.finishPullDown();
+                mAllAppsController.finishPullDown(false);
             }
             fromView.setVisibility(View.GONE);
             dispatchOnLauncherTransitionPrepare(fromView, animated, multiplePagesVisible);
index 7812a5b..344c389 100644 (file)
@@ -1532,7 +1532,6 @@ public class Workspace extends PagedView
         float finalAlpha = mHotseatAlpha[0] * mHotseatAlpha[1] * mHotseatAlpha[2];
 
         mLauncher.getHotseat().setAlpha(finalAlpha);
-        mPageIndicator.setAlpha(finalAlpha);
     }
 
     public ValueAnimator createHotseatAlphaAnimator(float finalValue) {
index 41e8518..f6e028b 100644 (file)
@@ -8,9 +8,11 @@ import android.util.Log;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.animation.AccelerateInterpolator;
+import android.view.animation.AnimationUtils;
 import android.view.animation.DecelerateInterpolator;
 import android.view.animation.Interpolator;
 
+import com.android.launcher3.pageindicators.CaretDrawable;
 import com.android.launcher3.DeviceProfile;
 import com.android.launcher3.Hotseat;
 import com.android.launcher3.Launcher;
@@ -50,6 +52,10 @@ public class AllAppsTransitionController implements TouchController, VerticalPul
     private Hotseat mHotseat;
     private float mHotseatBackgroundAlpha;
 
+    private ObjectAnimator mCaretAnimator;
+    private final long mCaretAnimationDuration;
+    private final Interpolator mCaretInterpolator;
+
     private float mStatusBarHeight;
 
     private final Launcher mLauncher;
@@ -67,13 +73,11 @@ public class AllAppsTransitionController implements TouchController, VerticalPul
 
     private static final float DEFAULT_SHIFT_RANGE = 10;
 
-
     private static final float RECATCH_REJECTION_FRACTION = .0875f;
 
     private int mBezelSwipeUpHeight;
     private long mAnimationDuration;
 
-
     private AnimatorSet mCurrentAnimation;
     private boolean mNoIntercept;
 
@@ -86,6 +90,11 @@ public class AllAppsTransitionController implements TouchController, VerticalPul
         mShiftCurrent = mShiftRange = DEFAULT_SHIFT_RANGE;
         mBezelSwipeUpHeight = launcher.getResources().getDimensionPixelSize(
                 R.dimen.all_apps_bezel_swipe_height);
+
+        mCaretAnimationDuration = launcher.getResources().getInteger(
+                R.integer.config_caretAnimationDuration);
+        mCaretInterpolator = AnimationUtils.loadInterpolator(launcher,
+                R.interpolator.caret_animation_interpolator);
     }
 
     @Override
@@ -398,7 +407,7 @@ public class AllAppsTransitionController implements TouchController, VerticalPul
                 if (canceled) {
                     return;
                 } else {
-                    finishPullDown();
+                    finishPullDown(true);
                     cleanUpAnimation();
                     mDetector.finishedScrolling();
                 }
@@ -413,14 +422,21 @@ public class AllAppsTransitionController implements TouchController, VerticalPul
     public void finishPullUp() {
         mHotseat.setVisibility(View.INVISIBLE);
         setProgress(0f);
+        animateCaret();
     }
 
-    public void finishPullDown() {
+    public void finishPullDown(boolean animated) {
         mAppsView.setVisibility(View.INVISIBLE);
         mHotseat.setBackgroundTransparent(false /* transparent */);
         mHotseat.setVisibility(View.VISIBLE);
         mAppsView.reset();
         setProgress(mShiftRange);
+        if (animated) {
+            animateCaret();
+        } else {
+            mWorkspace.getPageIndicator().getCaretDrawable()
+                    .setLevel(CaretDrawable.LEVEL_CARET_POINTING_UP);
+        }
     }
 
     private void cancelAnimation() {
@@ -435,10 +451,28 @@ public class AllAppsTransitionController implements TouchController, VerticalPul
         mCurrentAnimation = null;
     }
 
+    private void animateCaret() {
+        if (mCaretAnimator.isRunning()) {
+            mCaretAnimator.cancel(); // stop the animator in its tracks
+        }
+
+        if (mLauncher.isAllAppsVisible()) {
+            mCaretAnimator.setIntValues(CaretDrawable.LEVEL_CARET_POINTING_DOWN);
+        } else {
+            mCaretAnimator.setIntValues(CaretDrawable.LEVEL_CARET_POINTING_UP);
+        }
+
+        mCaretAnimator.start();
+    }
+
     public void setupViews(AllAppsContainerView appsView, Hotseat hotseat, Workspace workspace) {
         mAppsView = appsView;
         mHotseat = hotseat;
         mWorkspace = workspace;
+        mCaretAnimator = ObjectAnimator.ofInt(mWorkspace.getPageIndicator().getCaretDrawable(),
+                "level", CaretDrawable.LEVEL_CARET_POINTING_UP); // we will set values later
+        mCaretAnimator.setDuration(mCaretAnimationDuration);
+        mCaretAnimator.setInterpolator(mCaretInterpolator);
         mHotseat.addOnLayoutChangeListener(this);
     }
 
diff --git a/src/com/android/launcher3/pageindicators/CaretDrawable.java b/src/com/android/launcher3/pageindicators/CaretDrawable.java
new file mode 100644 (file)
index 0000000..3a7fc42
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.pageindicators;
+
+import android.content.Context;
+import android.content.res.Resources;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.Paint;
+import android.graphics.Path;
+import android.graphics.PixelFormat;
+
+import com.android.launcher3.R;
+
+import android.graphics.drawable.Drawable;
+
+public class CaretDrawable extends Drawable {
+    public static final int LEVEL_CARET_POINTING_UP = 0; // minimum possible level value
+    public static final int LEVEL_CARET_POINTING_DOWN = 10000; // maximum possible level value
+    public static final int LEVEL_CARET_NEUTRAL = LEVEL_CARET_POINTING_DOWN / 2;
+
+    private float mCaretProgress;
+
+    private Paint mPaint = new Paint();
+    private Path mPath = new Path();
+    private int mInset;
+
+    public CaretDrawable(Context context) {
+        final Resources res = context.getResources();
+
+        mPaint.setColor(res.getColor(R.color.all_apps_caret_color));
+        mPaint.setAntiAlias(true);
+        mPaint.setStrokeWidth(res.getDimensionPixelSize(R.dimen.all_apps_caret_stroke_width));
+        mPaint.setStyle(Paint.Style.STROKE);
+        mPaint.setStrokeCap(Paint.Cap.SQUARE);
+        mPaint.setStrokeJoin(Paint.Join.MITER);
+
+        mInset = res.getDimensionPixelSize(R.dimen.all_apps_caret_inset);
+    }
+
+    @Override
+    public void draw(Canvas canvas) {
+        final float width = getBounds().width();
+        final float height = getBounds().height();
+        final float left = getBounds().left;
+        final float top = getBounds().top;
+
+        final float verticalInset = (height / 4);
+        final float caretHeight = (height - (verticalInset * 2));
+
+        mPath.reset();
+        mPath.moveTo(left, top + caretHeight * (1 - mCaretProgress));
+        mPath.lineTo(left + (width / 2), top + caretHeight * mCaretProgress);
+        mPath.lineTo(left + width, top + caretHeight * (1 - mCaretProgress));
+
+        canvas.drawPath(mPath, mPaint);
+    }
+
+    @Override
+    protected boolean onLevelChange(int level) {
+        mCaretProgress = (float) level / (float) LEVEL_CARET_POINTING_DOWN;
+        invalidateSelf();
+        return true;
+    }
+
+    @Override
+    public int getOpacity() {
+        return PixelFormat.OPAQUE;
+    }
+
+    @Override
+    public void setAlpha(int alpha) {
+        // no-op
+    }
+
+    @Override
+    public void setColorFilter(ColorFilter cf) {
+        // no-op
+    }
+
+    @Override
+    public void setBounds(int left, int top, int right, int bottom) {
+        super.setBounds(left + mInset, top + mInset, right - mInset, bottom - mInset);
+    }
+}
index 2209bb8..b53715d 100644 (file)
@@ -16,6 +16,7 @@
 package com.android.launcher3.pageindicators;
 
 import android.content.Context;
+import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 import android.view.View;
 
@@ -25,6 +26,7 @@ import com.android.launcher3.dynamicui.ExtractedColors;
  * Base class for a page indicator.
  */
 public abstract class PageIndicator extends View {
+    private CaretDrawable mCaretDrawable;
 
     protected int mNumPages = 1;
 
@@ -45,14 +47,36 @@ public abstract class PageIndicator extends View {
         mNumPages--;
         onPageCountChanged();
     }
+
     public void setMarkersCount(int numMarkers) {
         mNumPages = numMarkers;
         onPageCountChanged();
     }
 
-    protected void onPageCountChanged() { }
+    public CaretDrawable getCaretDrawable() {
+        return mCaretDrawable;
+    }
+
+    public void setCaretDrawable(CaretDrawable caretDrawable) {
+        if (mCaretDrawable != null) {
+            mCaretDrawable.setCallback(null);
+        }
+
+        mCaretDrawable = caretDrawable;
+
+        if (mCaretDrawable != null) {
+            mCaretDrawable.setCallback(this);
+        }
+    }
+
+    protected void onPageCountChanged() {}
 
     public void setShouldAutoHide(boolean shouldAutoHide) {}
 
     public void updateColor(ExtractedColors extractedColors) {}
+
+    @Override
+    protected boolean verifyDrawable(Drawable who) {
+        return super.verifyDrawable(who) || who == getCaretDrawable();
+    }
 }
index 0f9145d..8075201 100644 (file)
 package com.android.launcher3.pageindicators;
 
 import android.content.Context;
-import android.content.res.Resources;
 import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
 import android.util.AttributeSet;
 
 import com.android.launcher3.Launcher;
-import com.android.launcher3.R;
-import com.android.launcher3.dynamicui.ExtractedColors;
 
 /**
  * Simply draws the caret drawable in the center. Used for the landscape layout.
  */
 public class PageIndicatorCaretLandscape extends PageIndicator {
     // all apps pull up handle drawable.
-    private final Drawable caretDrawable;
 
     public PageIndicatorCaretLandscape(Context context) {
         this(context, null);
@@ -43,8 +38,7 @@ public class PageIndicatorCaretLandscape extends PageIndicator {
     public PageIndicatorCaretLandscape(Context context, AttributeSet attrs, int defStyle) {
         super(context, attrs, defStyle);
 
-        Resources res = context.getResources();
-        caretDrawable = res.getDrawable(R.drawable.ic_allapps_caret);
+        setCaretDrawable(new CaretDrawable(context));
         Launcher l = (Launcher) context;
         setOnTouchListener(l.getHapticFeedbackTouchListener());
         setOnClickListener(l);
@@ -56,11 +50,11 @@ public class PageIndicatorCaretLandscape extends PageIndicator {
         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);
+        getCaretDrawable().setBounds(l, 0, l + size, size);
     }
 
     @Override
     protected void onDraw(Canvas canvas) {
-        caretDrawable.draw(canvas);
+        getCaretDrawable().draw(canvas);
     }
 }
index 2c157b4..4403b5a 100644 (file)
@@ -10,7 +10,6 @@ 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;
@@ -61,8 +60,6 @@ public class PageIndicatorLineCaret extends PageIndicator {
     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;
@@ -134,7 +131,7 @@ public class PageIndicatorLineCaret extends PageIndicator {
         setOnClickListener(mLauncher);
         setOnFocusChangeListener(mLauncher.mFocusHandler);
         Resources res = context.getResources();
-        caretDrawable = res.getDrawable(R.drawable.ic_allapps_caret);
+        setCaretDrawable(new CaretDrawable(context));
         mLineHeight = res.getDimensionPixelSize(R.dimen.dynamic_grid_page_indicator_line_height);
         mTouchExtensionHeight = res.getDimensionPixelSize(
                 R.dimen.dynamic_grid_page_indicator_extra_touch_height);
@@ -145,7 +142,7 @@ public class PageIndicatorLineCaret extends PageIndicator {
         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);
+        getCaretDrawable().setBounds(l, 0, l + size, size);
 
         // The touch area is expanded below this view by #mTouchExtensionHeight
         // which extends to the top of the hotseat.
@@ -159,7 +156,7 @@ public class PageIndicatorLineCaret extends PageIndicator {
 
     @Override
     protected void onDraw(Canvas canvas) {
-        caretDrawable.draw(canvas);
+        getCaretDrawable().draw(canvas);
         if (mTotalScroll == 0 || mNumPagesFloat == 0) {
             return;
         }