Merge "Removing custom state definition from FastBitmapDrawable" into ub-launcher3-dorval

am: ea53ca3a17

Change-Id: Id326b16aabafa1be2e93f562df3e32008310af9e
This commit is contained in:
Sunny Goyal
2017-02-24 00:41:32 +00:00
committed by android-build-merger
7 changed files with 135 additions and 235 deletions
@@ -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>
+1
View File
@@ -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"
@@ -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") {
+16 -72
View File
@@ -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,14 +233,21 @@ 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. */
public Drawable getIcon() {
return mIcon;
@@ -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.
*/
@@ -629,21 +588,6 @@ public class BubbleTextView extends TextView
.isEmpty();
}
/**
* 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.
*/
+53 -127
View File
@@ -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) {
@@ -306,49 +282,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]
*/
@@ -435,11 +368,4 @@ public class FastBitmapDrawable extends Drawable {
}
invalidateSelf();
}
private AnimatorSet cancelAnimator(AnimatorSet animator) {
if (animator != null) {
animator.cancel();
}
return null;
}
}
@@ -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);
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);
}
}
/**
* 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;
}
v.setFastScrollFocusState(newState, animated);
}
}