diff options
author | Sunny Goyal <sunnygoyal@google.com> | 2017-02-16 13:33:15 -0800 |
---|---|---|
committer | Sunny Goyal <sunnygoyal@google.com> | 2017-02-23 16:15:25 -0800 |
commit | 2a76e3fbc654481eb05ac3187896884ad1497b9f (patch) | |
tree | c5b1aa7edd31277e487bada373da308e8234c487 | |
parent | f28629a47b5fcd9532683e9c9ad7aad049e0106d (diff) | |
download | Launcher3-2a76e3fbc654481eb05ac3187896884ad1497b9f.tar.gz |
Removing custom state definition from FastBitmapDrawable
> For Fast scrolling, using state list animator defined in xml
> For Pressed state, using onState change method in a drawable
Change-Id: Ia608690f593938cf0f77e00afcc2a3076e48d8f4
-rw-r--r-- | res/animator/all_apps_fastscroll_icon_anim.xml | 49 | ||||
-rw-r--r-- | res/animator/overview_button_anim.xml (renamed from res/animator-v21/overview_button_anim.xml) | 0 | ||||
-rw-r--r-- | res/layout/all_apps_icon.xml | 1 | ||||
-rw-r--r-- | src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java | 4 | ||||
-rw-r--r-- | src/com/android/launcher3/BubbleTextView.java | 88 | ||||
-rw-r--r-- | src/com/android/launcher3/FastBitmapDrawable.java | 180 | ||||
-rw-r--r-- | src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java | 48 |
7 files changed, 135 insertions, 235 deletions
diff --git a/res/animator/all_apps_fastscroll_icon_anim.xml b/res/animator/all_apps_fastscroll_icon_anim.xml new file mode 100644 index 0000000000..380b009a6a --- /dev/null +++ b/res/animator/all_apps_fastscroll_icon_anim.xml @@ -0,0 +1,49 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + Copyright 2017, 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. +--> +<selector xmlns:android="http://schemas.android.com/apk/res/android"> + + <item android:state_activated="true"> + <set> + <objectAnimator + android:duration="225" + android:propertyName="scaleX" + android:valueTo="1.15" + android:valueType="floatType" /> + <objectAnimator + android:duration="225" + android:propertyName="scaleY" + android:valueTo="1.15" + android:valueType="floatType" /> + </set> + </item> + + <item> + <set> + <objectAnimator + android:duration="275" + android:propertyName="scaleX" + android:valueTo="1" + android:valueType="floatType" /> + <objectAnimator + android:duration="275" + android:propertyName="scaleY" + android:valueTo="1" + android:valueType="floatType" /> + </set> + </item> + +</selector>
\ No newline at end of file diff --git a/res/animator-v21/overview_button_anim.xml b/res/animator/overview_button_anim.xml index aac3d26555..aac3d26555 100644 --- a/res/animator-v21/overview_button_anim.xml +++ b/res/animator/overview_button_anim.xml diff --git a/res/layout/all_apps_icon.xml b/res/layout/all_apps_icon.xml index 1e83041d5d..ca0cbcc4df 100644 --- a/res/layout/all_apps_icon.xml +++ b/res/layout/all_apps_icon.xml @@ -20,6 +20,7 @@ android:id="@+id/icon" android:layout_width="match_parent" android:layout_height="wrap_content" + android:stateListAnimator="@animator/all_apps_fastscroll_icon_anim" launcher:iconDisplay="all_apps" launcher:centerVertically="true" android:paddingLeft="4dp" diff --git a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java index ba7c3f809c..5feb42ea8b 100644 --- a/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java +++ b/src/com/android/launcher3/BaseRecyclerViewFastScrollBar.java @@ -36,10 +36,6 @@ import com.android.launcher3.util.Themes; */ public class BaseRecyclerViewFastScrollBar { - public interface FastScrollFocusableView { - void setFastScrollFocusState(final FastBitmapDrawable.State focusState, boolean animated); - } - private static final Property<BaseRecyclerViewFastScrollBar, Integer> TRACK_WIDTH = new Property<BaseRecyclerViewFastScrollBar, Integer>(Integer.class, "width") { diff --git a/src/com/android/launcher3/BubbleTextView.java b/src/com/android/launcher3/BubbleTextView.java index 1a41e08db3..107d7006aa 100644 --- a/src/com/android/launcher3/BubbleTextView.java +++ b/src/com/android/launcher3/BubbleTextView.java @@ -53,8 +53,7 @@ import java.text.NumberFormat; * because we want to make the bubble taller than the text and TextView's clip is * too aggressive. */ -public class BubbleTextView extends TextView - implements BaseRecyclerViewFastScrollBar.FastScrollFocusableView, ItemInfoUpdateReceiver { +public class BubbleTextView extends TextView implements ItemInfoUpdateReceiver { // Dimensions in DP private static final float AMBIENT_SHADOW_RADIUS = 2.5f; @@ -67,6 +66,8 @@ public class BubbleTextView extends TextView private static final int DISPLAY_ALL_APPS = 1; private static final int DISPLAY_FOLDER = 2; + private static final int[] STATE_PRESSED = new int[] {android.R.attr.state_pressed}; + private final Launcher mLauncher; private Drawable mIcon; private final boolean mCenterVertically; @@ -232,12 +233,19 @@ public class BubbleTextView extends TextView } @Override - public void setPressed(boolean pressed) { - super.setPressed(pressed); - + public void refreshDrawableState() { if (!mIgnorePressedStateChange) { - updateIconState(); + super.refreshDrawableState(); + } + } + + @Override + protected int[] onCreateDrawableState(int extraSpace) { + final int[] drawableState = super.onCreateDrawableState(extraSpace + 1); + if (mStayPressed) { + mergeDrawableStates(drawableState, STATE_PRESSED); } + return drawableState; } /** Returns the icon for this view. */ @@ -250,17 +258,6 @@ public class BubbleTextView extends TextView return mLayoutHorizontal; } - private void updateIconState() { - if (mIcon instanceof FastBitmapDrawable) { - FastBitmapDrawable d = (FastBitmapDrawable) mIcon; - if (isPressed() || mStayPressed) { - d.animateState(FastBitmapDrawable.State.PRESSED); - } else { - d.animateState(FastBitmapDrawable.State.NORMAL); - } - } - } - @Override public void setOnLongClickListener(OnLongClickListener l) { super.setOnLongClickListener(l); @@ -334,7 +331,7 @@ public class BubbleTextView extends TextView this, mPressedBackground); } - updateIconState(); + refreshDrawableState(); } void clearPressedBackground() { @@ -364,7 +361,7 @@ public class BubbleTextView extends TextView mPressedBackground = null; mIgnorePressedStateChange = false; - updateIconState(); + refreshDrawableState(); return result; } @@ -544,10 +541,6 @@ public class BubbleTextView extends TextView @Override public void reapplyItemInfo(ItemInfoWithIcon info) { if (getTag() == info) { - FastBitmapDrawable.State prevState = FastBitmapDrawable.State.NORMAL; - if (mIcon instanceof FastBitmapDrawable) { - prevState = ((FastBitmapDrawable) mIcon).getCurrentState(); - } mIconLoadRequest = null; mDisableRelayout = true; @@ -566,12 +559,6 @@ public class BubbleTextView extends TextView applyFromPackageItemInfo((PackageItemInfo) info); } - // If we are reapplying over an old icon, then we should update the new icon to the same - // state as the old icon - if (mIcon instanceof FastBitmapDrawable) { - ((FastBitmapDrawable) mIcon).setState(prevState); - } - mDisableRelayout = false; } } @@ -593,34 +580,6 @@ public class BubbleTextView extends TextView } } - @Override - public void setFastScrollFocusState(final FastBitmapDrawable.State focusState, boolean animated) { - // We can only set the fast scroll focus state on a FastBitmapDrawable - if (!(mIcon instanceof FastBitmapDrawable)) { - return; - } - - FastBitmapDrawable d = (FastBitmapDrawable) mIcon; - if (animated) { - FastBitmapDrawable.State prevState = d.getCurrentState(); - if (d.animateState(focusState)) { - // If the state was updated, then update the view accordingly - animate().scaleX(focusState.viewScale) - .scaleY(focusState.viewScale) - .setStartDelay(getStartDelayForStateChange(prevState, focusState)) - .setDuration(d.getDurationForStateChange(prevState, focusState)) - .start(); - } - } else { - if (d.setState(focusState)) { - // If the state was updated, then update the view accordingly - animate().cancel(); - setScaleX(focusState.viewScale); - setScaleY(focusState.viewScale); - } - } - } - /** * Returns true if the view can show custom shortcuts. */ @@ -630,21 +589,6 @@ public class BubbleTextView extends TextView } /** - * Returns the start delay when animating between certain {@link FastBitmapDrawable} states. - */ - private static int getStartDelayForStateChange(final FastBitmapDrawable.State fromState, - final FastBitmapDrawable.State toState) { - switch (toState) { - case NORMAL: - switch (fromState) { - case FAST_SCROLL_HIGHLIGHTED: - return FastBitmapDrawable.FAST_SCROLL_INACTIVE_DURATION / 4; - } - } - return 0; - } - - /** * Interface to be implemented by the grand parent to allow click shadow effect. */ public interface BubbleTextShadowHandler { diff --git a/src/com/android/launcher3/FastBitmapDrawable.java b/src/com/android/launcher3/FastBitmapDrawable.java index 1f74c88777..be3ba90145 100644 --- a/src/com/android/launcher3/FastBitmapDrawable.java +++ b/src/com/android/launcher3/FastBitmapDrawable.java @@ -16,7 +16,6 @@ package com.android.launcher3; -import android.animation.AnimatorSet; import android.animation.ObjectAnimator; import android.animation.TimeInterpolator; import android.graphics.Bitmap; @@ -32,42 +31,19 @@ import android.graphics.PorterDuffColorFilter; import android.graphics.drawable.Drawable; import android.util.Property; import android.util.SparseArray; -import android.view.animation.DecelerateInterpolator; import com.android.launcher3.badge.BadgeInfo; import com.android.launcher3.badge.BadgeRenderer; import com.android.launcher3.graphics.IconPalette; public class FastBitmapDrawable extends Drawable { + + private static final int[] STATE_PRESSED = new int[] {android.R.attr.state_pressed}; + + private static final float PRESSED_BRIGHTNESS = 100f / 255f; private static final float DISABLED_DESATURATION = 1f; private static final float DISABLED_BRIGHTNESS = 0.5f; - /** - * The possible states that a FastBitmapDrawable can be in. - */ - public enum State { - - NORMAL (0f, 0f, 1f, new DecelerateInterpolator()), - PRESSED (0f, 100f / 255f, 1f, CLICK_FEEDBACK_INTERPOLATOR), - FAST_SCROLL_HIGHLIGHTED (0f, 0f, 1.15f, new DecelerateInterpolator()), - FAST_SCROLL_UNHIGHLIGHTED (0f, 0f, 1f, new DecelerateInterpolator()); - - public final float desaturation; - public final float brightness; - /** - * Used specifically by the view drawing this FastBitmapDrawable. - */ - public final float viewScale; - public final TimeInterpolator interpolator; - - State(float desaturation, float brightness, float viewScale, TimeInterpolator interpolator) { - this.desaturation = desaturation; - this.brightness = brightness; - this.viewScale = viewScale; - this.interpolator = interpolator; - } - } - public static final TimeInterpolator CLICK_FEEDBACK_INTERPOLATOR = new TimeInterpolator() { @Override @@ -82,10 +58,6 @@ public class FastBitmapDrawable extends Drawable { } }; public static final int CLICK_FEEDBACK_DURATION = 2000; - public static final int FAST_SCROLL_HIGHLIGHT_DURATION = 225; - public static final int FAST_SCROLL_UNHIGHLIGHT_DURATION = 150; - public static final int FAST_SCROLL_UNHIGHLIGHT_FROM_NORMAL_DURATION = 225; - public static final int FAST_SCROLL_INACTIVE_DURATION = 275; // Since we don't need 256^2 values for combinations of both the brightness and saturation, we // reduce the value space to a smaller value V, which reduces the number of cached @@ -101,7 +73,8 @@ public class FastBitmapDrawable extends Drawable { protected final Paint mPaint = new Paint(Paint.FILTER_BITMAP_FLAG | Paint.ANTI_ALIAS_FLAG); private final Bitmap mBitmap; - private State mState = State.NORMAL; + + private boolean mIsPressed; private boolean mIsDisabled; private BadgeInfo mBadgeInfo; @@ -123,6 +96,19 @@ public class FastBitmapDrawable extends Drawable { } }; + private static final Property<FastBitmapDrawable, Float> BRIGHTNESS + = new Property<FastBitmapDrawable, Float>(Float.TYPE, "brightness") { + @Override + public Float get(FastBitmapDrawable fastBitmapDrawable) { + return fastBitmapDrawable.getBrightness(); + } + + @Override + public void set(FastBitmapDrawable fastBitmapDrawable, Float value) { + fastBitmapDrawable.setBrightness(value); + } + }; + // The saturation and brightness are values that are mapped to REDUCED_FILTER_VALUE_SPACE and // as a result, can be used to compose the key for the cached ColorMatrixColorFilters private int mDesaturation = 0; @@ -130,8 +116,8 @@ public class FastBitmapDrawable extends Drawable { private int mAlpha = 255; private int mPrevUpdateKey = Integer.MAX_VALUE; - // Animators for the fast bitmap drawable's properties - private AnimatorSet mPropertyAnimator; + // Animators for the fast bitmap drawable's brightness + private ObjectAnimator mBrightnessAnimator; public FastBitmapDrawable(Bitmap b) { mBitmap = b; @@ -243,60 +229,50 @@ public class FastBitmapDrawable extends Drawable { return mBitmap; } - /** - * Animates this drawable to a new state. - * - * @return whether the state has changed. - */ - public boolean animateState(State newState) { - State prevState = mState; - if (mState != newState) { - mState = newState; - - float desaturation = mIsDisabled ? DISABLED_DESATURATION : newState.desaturation; - float brightness = mIsDisabled ? DISABLED_BRIGHTNESS: newState.brightness; - - mPropertyAnimator = cancelAnimator(mPropertyAnimator); - mPropertyAnimator = new AnimatorSet(); - mPropertyAnimator.playTogether( - ObjectAnimator.ofFloat(this, "desaturation", desaturation), - ObjectAnimator.ofFloat(this, "brightness", brightness)); - mPropertyAnimator.setInterpolator(newState.interpolator); - mPropertyAnimator.setDuration(getDurationForStateChange(prevState, newState)); - mPropertyAnimator.setStartDelay(getStartDelayForStateChange(prevState, newState)); - mPropertyAnimator.start(); - return true; - } - return false; + @Override + public boolean isStateful() { + return true; } - /** - * Immediately sets this drawable to a new state. - * - * @return whether the state has changed. - */ - public boolean setState(State newState) { - if (mState != newState) { - mState = newState; + @Override + protected boolean onStateChange(int[] state) { + boolean isPressed = false; + for (int s : state) { + if (s == android.R.attr.state_pressed) { + isPressed = true; + break; + } + } + if (mIsPressed != isPressed) { + mIsPressed = isPressed; - mPropertyAnimator = cancelAnimator(mPropertyAnimator); + if (mBrightnessAnimator != null) { + mBrightnessAnimator.cancel(); + } - invalidateDesaturationAndBrightness(); + if (mIsPressed) { + // Animate when going to pressed state + mBrightnessAnimator = ObjectAnimator.ofFloat( + this, BRIGHTNESS, getExpectedBrightness()); + mBrightnessAnimator.setDuration(CLICK_FEEDBACK_DURATION); + mBrightnessAnimator.setInterpolator(CLICK_FEEDBACK_INTERPOLATOR); + mBrightnessAnimator.start(); + } else { + setBrightness(getExpectedBrightness()); + } return true; } return false; } private void invalidateDesaturationAndBrightness() { - setDesaturation(mIsDisabled ? DISABLED_DESATURATION : mState.desaturation); - setBrightness(mIsDisabled ? DISABLED_BRIGHTNESS: mState.brightness); + setDesaturation(mIsDisabled ? DISABLED_DESATURATION : 0); + setBrightness(getExpectedBrightness()); } - /** - * Returns the current state. - */ - public State getCurrentState() { - return mState; + private float getExpectedBrightness() { + return mIsDisabled ? DISABLED_BRIGHTNESS : + (mIsPressed ? PRESSED_BRIGHTNESS : 0); } public void setIsDisabled(boolean isDisabled) { @@ -307,49 +283,6 @@ public class FastBitmapDrawable extends Drawable { } /** - * Returns the duration for the state change animation. - */ - public static int getDurationForStateChange(State fromState, State toState) { - switch (toState) { - case NORMAL: - switch (fromState) { - case PRESSED: - return 0; - case FAST_SCROLL_HIGHLIGHTED: - case FAST_SCROLL_UNHIGHLIGHTED: - return FAST_SCROLL_INACTIVE_DURATION; - } - case PRESSED: - return CLICK_FEEDBACK_DURATION; - case FAST_SCROLL_HIGHLIGHTED: - return FAST_SCROLL_HIGHLIGHT_DURATION; - case FAST_SCROLL_UNHIGHLIGHTED: - switch (fromState) { - case NORMAL: - // When animating from normal state, take a little longer - return FAST_SCROLL_UNHIGHLIGHT_FROM_NORMAL_DURATION; - default: - return FAST_SCROLL_UNHIGHLIGHT_DURATION; - } - } - return 0; - } - - /** - * Returns the start delay when animating between certain fast scroll states. - */ - public static int getStartDelayForStateChange(State fromState, State toState) { - switch (toState) { - case FAST_SCROLL_UNHIGHLIGHTED: - switch (fromState) { - case NORMAL: - return FAST_SCROLL_UNHIGHLIGHT_DURATION / 4; - } - } - return 0; - } - - /** * Sets the saturation of this icon, 0 [full color] -> 1 [desaturated] */ private void setDesaturation(float desaturation) { @@ -435,11 +368,4 @@ public class FastBitmapDrawable extends Drawable { } invalidateSelf(); } - - private AnimatorSet cancelAnimator(AnimatorSet animator) { - if (animator != null) { - animator.cancel(); - } - return null; - } } diff --git a/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java b/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java index 28b7685ed4..a1ff8223a2 100644 --- a/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java +++ b/src/com/android/launcher3/allapps/AllAppsFastScrollHelper.java @@ -19,6 +19,7 @@ import android.support.v7.widget.RecyclerView; import android.view.View; import com.android.launcher3.BaseRecyclerViewFastScrollBar; +import com.android.launcher3.BubbleTextView; import com.android.launcher3.FastBitmapDrawable; import com.android.launcher3.util.Thunk; @@ -45,8 +46,7 @@ public class AllAppsFastScrollHelper implements AllAppsGridAdapter.BindViewCallb // Set of all views animated during fast scroll. We keep track of these ourselves since there // is no way to reset a view once it gets scrapped or recycled without other hacks - private HashSet<BaseRecyclerViewFastScrollBar.FastScrollFocusableView> mTrackedFastScrollViews = - new HashSet<>(); + private HashSet<RecyclerView.ViewHolder> mTrackedFastScrollViews = new HashSet<>(); // Smooth fast-scroll animation frames @Thunk int mFastScrollFrameIndex; @@ -186,12 +186,7 @@ public class AllAppsFastScrollHelper implements AllAppsGridAdapter.BindViewCallb public void onBindView(AllAppsGridAdapter.ViewHolder holder) { // Update newly bound views to the current fast scroll state if we are fast scrolling if (mCurrentFastScrollSection != null || mTargetFastScrollSection != null) { - if (holder.itemView instanceof BaseRecyclerViewFastScrollBar.FastScrollFocusableView) { - BaseRecyclerViewFastScrollBar.FastScrollFocusableView v = - (BaseRecyclerViewFastScrollBar.FastScrollFocusableView) holder.itemView; - updateViewFastScrollFocusState(v, holder.getPosition(), false /* animated */); - mTrackedFastScrollViews.add(v); - } + mTrackedFastScrollViews.add(holder); } } @@ -201,9 +196,9 @@ public class AllAppsFastScrollHelper implements AllAppsGridAdapter.BindViewCallb private void trackAllChildViews() { int childCount = mRv.getChildCount(); for (int i = 0; i < childCount; i++) { - View v = mRv.getChildAt(i); - if (v instanceof BaseRecyclerViewFastScrollBar.FastScrollFocusableView) { - mTrackedFastScrollViews.add((BaseRecyclerViewFastScrollBar.FastScrollFocusableView) v); + RecyclerView.ViewHolder viewHolder = mRv.getChildViewHolder(mRv.getChildAt(i)); + if (viewHolder != null) { + mTrackedFastScrollViews.add(viewHolder); } } } @@ -212,27 +207,16 @@ public class AllAppsFastScrollHelper implements AllAppsGridAdapter.BindViewCallb * Updates the fast scroll focus on all the children. */ private void updateTrackedViewsFastScrollFocusState() { - for (BaseRecyclerViewFastScrollBar.FastScrollFocusableView v : mTrackedFastScrollViews) { - RecyclerView.ViewHolder viewHolder = mRv.getChildViewHolder((View) v); - int pos = (viewHolder != null) ? viewHolder.getPosition() : -1; - updateViewFastScrollFocusState(v, pos, true); - } - } - - /** - * Updates the fast scroll focus on all a given view. - */ - private void updateViewFastScrollFocusState(BaseRecyclerViewFastScrollBar.FastScrollFocusableView v, - int pos, boolean animated) { - FastBitmapDrawable.State newState = FastBitmapDrawable.State.NORMAL; - if (mCurrentFastScrollSection != null && pos > -1) { - AlphabeticalAppsList.AdapterItem item = mApps.getAdapterItems().get(pos); - boolean highlight = item.sectionName.equals(mCurrentFastScrollSection) && - item.position == mTargetFastScrollPosition; - newState = highlight ? - FastBitmapDrawable.State.FAST_SCROLL_HIGHLIGHTED : - FastBitmapDrawable.State.FAST_SCROLL_UNHIGHLIGHTED; + for (RecyclerView.ViewHolder viewHolder : mTrackedFastScrollViews) { + int pos = viewHolder.getAdapterPosition(); + boolean isActive = false; + if (mCurrentFastScrollSection != null && pos > -1) { + AlphabeticalAppsList.AdapterItem item = mApps.getAdapterItems().get(pos); + isActive = item != null && + mCurrentFastScrollSection.equals(item.sectionName) && + item.position == mTargetFastScrollPosition; + } + viewHolder.itemView.setActivated(isActive); } - v.setFastScrollFocusState(newState, animated); } } |