Merge "Fix jump in animation for hotseat while re-arranging icons" into tm-dev am: 49cb99a420

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/Launcher3/+/16967985

Change-Id: If51c5c2c7fc34a0584f59aa684125f2294383362
This commit is contained in:
TreeHugger Robot
2022-02-23 17:24:19 +00:00
committed by Automerger Merge Worker
7 changed files with 81 additions and 43 deletions
@@ -22,7 +22,7 @@ import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.HINT_STATE_TWO_BUTTON; import static com.android.launcher3.LauncherState.HINT_STATE_TWO_BUTTON;
import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.LauncherState.OVERVIEW; import static com.android.launcher3.LauncherState.OVERVIEW;
import static com.android.launcher3.WorkspaceStateTransitionAnimation.getSpringScaleAnimator; import static com.android.launcher3.WorkspaceStateTransitionAnimation.getWorkspaceSpringScaleAnimator;
import static com.android.launcher3.anim.Interpolators.ACCEL; import static com.android.launcher3.anim.Interpolators.ACCEL;
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL; import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
import static com.android.launcher3.anim.Interpolators.DEACCEL; import static com.android.launcher3.anim.Interpolators.DEACCEL;
@@ -172,7 +172,8 @@ public class QuickstepAtomicAnimationFactory extends
} else if (fromState == HINT_STATE && toState == NORMAL) { } else if (fromState == HINT_STATE && toState == NORMAL) {
config.setInterpolator(ANIM_DEPTH, DEACCEL_3); config.setInterpolator(ANIM_DEPTH, DEACCEL_3);
if (mHintToNormalDuration == -1) { if (mHintToNormalDuration == -1) {
ValueAnimator va = getSpringScaleAnimator(mActivity, mActivity.getWorkspace(), ValueAnimator va = getWorkspaceSpringScaleAnimator(mActivity,
mActivity.getWorkspace(),
toState.getWorkspaceScaleAndTranslation(mActivity).scale); toState.getWorkspaceScaleAndTranslation(mActivity).scale);
mHintToNormalDuration = (int) va.getDuration(); mHintToNormalDuration = (int) va.getDuration();
} }
@@ -15,14 +15,14 @@
*/ */
package com.android.quickstep.util; package com.android.quickstep.util;
import static com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY;
import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_UNFOLD_ANIMATION; import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_UNFOLD_ANIMATION;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY_FACTORY; import static com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY;
import static com.android.launcher3.Utilities.comp; import static com.android.launcher3.Utilities.comp;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.util.FloatProperty; import android.util.FloatProperty;
import android.util.MathUtils; import android.util.MathUtils;
import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import android.view.WindowManagerGlobal; import android.view.WindowManagerGlobal;
@@ -30,6 +30,7 @@ import androidx.core.view.OneShotPreDrawListener;
import com.android.launcher3.Hotseat; import com.android.launcher3.Hotseat;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.Workspace;
import com.android.launcher3.util.HorizontalInsettableView; import com.android.launcher3.util.HorizontalInsettableView;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider; import com.android.systemui.unfold.UnfoldTransitionProgressProvider;
import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener; import com.android.systemui.unfold.UnfoldTransitionProgressProvider.TransitionProgressListener;
@@ -44,8 +45,10 @@ public class LauncherUnfoldAnimationController {
// Percentage of the width of the quick search bar that will be reduced // Percentage of the width of the quick search bar that will be reduced
// from the both sides of the bar when progress is 0 // from the both sides of the bar when progress is 0
private static final float MAX_WIDTH_INSET_FRACTION = 0.15f; private static final float MAX_WIDTH_INSET_FRACTION = 0.15f;
private static final FloatProperty<View> UNFOLD_SCALE_PROPERTY = private static final FloatProperty<Workspace> WORKSPACE_SCALE_PROPERTY =
SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION); WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION);
private static final FloatProperty<Hotseat> HOTSEAT_SCALE_PROPERTY =
HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION);
private final Launcher mLauncher; private final Launcher mLauncher;
private final ScopedUnfoldTransitionProgressProvider mProgressProvider; private final ScopedUnfoldTransitionProgressProvider mProgressProvider;
@@ -154,8 +157,8 @@ public class LauncherUnfoldAnimationController {
} }
private void setScale(float value) { private void setScale(float value) {
UNFOLD_SCALE_PROPERTY.setValue(mLauncher.getWorkspace(), value); WORKSPACE_SCALE_PROPERTY.setValue(mLauncher.getWorkspace(), value);
UNFOLD_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value); HOTSEAT_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value);
} }
} }
} }
@@ -15,8 +15,9 @@
*/ */
package com.android.quickstep.util; package com.android.quickstep.util;
import static com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY;
import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_REVEAL_ANIM; import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_REVEAL_ANIM;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY_FACTORY; import static com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY;
import static com.android.launcher3.LauncherState.BACKGROUND_APP; import static com.android.launcher3.LauncherState.BACKGROUND_APP;
import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.LauncherState.NORMAL;
import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER; import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER;
@@ -32,6 +33,7 @@ import android.util.FloatProperty;
import android.view.View; import android.view.View;
import com.android.launcher3.BaseQuickstepLauncher; import com.android.launcher3.BaseQuickstepLauncher;
import com.android.launcher3.Hotseat;
import com.android.launcher3.Launcher; import com.android.launcher3.Launcher;
import com.android.launcher3.R; import com.android.launcher3.R;
import com.android.launcher3.Workspace; import com.android.launcher3.Workspace;
@@ -51,8 +53,11 @@ public class WorkspaceRevealAnim {
// Should be used for animations running alongside this WorkspaceRevealAnim. // Should be used for animations running alongside this WorkspaceRevealAnim.
public static final int DURATION_MS = 350; public static final int DURATION_MS = 350;
private static final FloatProperty<View> REVEAL_SCALE_PROPERTY = private static final FloatProperty<Workspace> WORKSPACE_SCALE_PROPERTY =
SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_REVEAL_ANIM); WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_REVEAL_ANIM);
private static final FloatProperty<Hotseat> HOTSEAT_SCALE_PROPERTY =
HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_REVEAL_ANIM);
private final float mScaleStart; private final float mScaleStart;
private final AnimatorSet mAnimators = new AnimatorSet(); private final AnimatorSet mAnimators = new AnimatorSet();
@@ -67,8 +72,8 @@ public class WorkspaceRevealAnim {
workspace.setPivotToScaleWithSelf(launcher.getHotseat()); workspace.setPivotToScaleWithSelf(launcher.getHotseat());
// Add reveal animations. // Add reveal animations.
addRevealAnimatorsForView(workspace); addRevealAnimatorsForView(workspace, WORKSPACE_SCALE_PROPERTY);
addRevealAnimatorsForView(launcher.getHotseat()); addRevealAnimatorsForView(launcher.getHotseat(), HOTSEAT_SCALE_PROPERTY);
// Add overview scrim animation. // Add overview scrim animation.
if (animateOverviewScrim) { if (animateOverviewScrim) {
@@ -93,8 +98,8 @@ public class WorkspaceRevealAnim {
mAnimators.setInterpolator(Interpolators.DECELERATED_EASE); mAnimators.setInterpolator(Interpolators.DECELERATED_EASE);
} }
private void addRevealAnimatorsForView(View v) { private <T extends View> void addRevealAnimatorsForView(T v, FloatProperty<T> scaleProperty) {
ObjectAnimator scale = ObjectAnimator.ofFloat(v, REVEAL_SCALE_PROPERTY, mScaleStart, 1f); ObjectAnimator scale = ObjectAnimator.ofFloat(v, scaleProperty, mScaleStart, 1f);
scale.setDuration(DURATION_MS); scale.setDuration(DURATION_MS);
scale.setInterpolator(Interpolators.DECELERATED_EASE); scale.setInterpolator(Interpolators.DECELERATED_EASE);
mAnimators.play(scale); mAnimators.play(scale);
@@ -107,7 +112,7 @@ public class WorkspaceRevealAnim {
mAnimators.addListener(new AnimatorListenerAdapter() { mAnimators.addListener(new AnimatorListenerAdapter() {
@Override @Override
public void onAnimationEnd(Animator animation) { public void onAnimationEnd(Animator animation) {
REVEAL_SCALE_PROPERTY.set(v, 1f); scaleProperty.set(v, 1f);
v.setAlpha(1f); v.setAlpha(1f);
} }
}); });
@@ -67,18 +67,16 @@ public class LauncherAnimUtils {
}; };
/** /**
* Property to set the scale of workspace and hotseat. The value is based on a combination * Property to set the scale of workspace. The value is based on a combination
* of all the ones set, to have a smooth experience even in the case of overlapping scaling * of all the ones set, to have a smooth experience even in the case of overlapping scaling
* animation. * animation.
*/ */
public static final MultiScalePropertyFactory<View> SCALE_PROPERTY_FACTORY = public static final MultiScalePropertyFactory<Workspace> WORKSPACE_SCALE_PROPERTY_FACTORY =
new MultiScalePropertyFactory<View>("scale_property") { new MultiScalePropertyFactory<Workspace>("workspace_scale_property");
@Override
protected void apply(View view, float scale) { /** Property to set the scale of hotseat. */
view.setScaleX(scale); public static final MultiScalePropertyFactory<Hotseat> HOTSEAT_SCALE_PROPERTY_FACTORY =
view.setScaleY(scale); new MultiScalePropertyFactory<Hotseat>("hotseat_scale_property");
}
};
public static final int SCALE_INDEX_UNFOLD_ANIMATION = 1; public static final int SCALE_INDEX_UNFOLD_ANIMATION = 1;
public static final int SCALE_INDEX_UNLOCK_ANIMATION = 2; public static final int SCALE_INDEX_UNLOCK_ANIMATION = 2;
@@ -18,11 +18,12 @@ package com.android.launcher3;
import static androidx.dynamicanimation.animation.DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE; import static androidx.dynamicanimation.animation.DynamicAnimation.MIN_VISIBLE_CHANGE_SCALE;
import static com.android.launcher3.LauncherAnimUtils.HOTSEAT_SCALE_PROPERTY_FACTORY;
import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_WORKSPACE_STATE; import static com.android.launcher3.LauncherAnimUtils.SCALE_INDEX_WORKSPACE_STATE;
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY_FACTORY;
import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA; import static com.android.launcher3.LauncherAnimUtils.VIEW_ALPHA;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X; import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_X;
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y; import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
import static com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY;
import static com.android.launcher3.LauncherState.FLAG_HAS_SYS_UI_SCRIM; import static com.android.launcher3.LauncherState.FLAG_HAS_SYS_UI_SCRIM;
import static com.android.launcher3.LauncherState.HINT_STATE; import static com.android.launcher3.LauncherState.HINT_STATE;
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS; import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
@@ -64,8 +65,11 @@ import com.android.systemui.plugins.ResourceProvider;
*/ */
public class WorkspaceStateTransitionAnimation { public class WorkspaceStateTransitionAnimation {
private static final FloatProperty<View> WORKSPACE_STATE_SCALE_PROPERTY = private static final FloatProperty<Workspace> WORKSPACE_SCALE_PROPERTY =
SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_WORKSPACE_STATE); WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_WORKSPACE_STATE);
private static final FloatProperty<Hotseat> HOTSEAT_SCALE_PROPERTY =
HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_WORKSPACE_STATE);
private final Launcher mLauncher; private final Launcher mLauncher;
private final Workspace mWorkspace; private final Workspace mWorkspace;
@@ -120,9 +124,9 @@ public class WorkspaceStateTransitionAnimation {
&& fromState == HINT_STATE && state == NORMAL; && fromState == HINT_STATE && state == NORMAL;
if (shouldSpring) { if (shouldSpring) {
((PendingAnimation) propertySetter).add(getSpringScaleAnimator(mLauncher, ((PendingAnimation) propertySetter).add(getSpringScaleAnimator(mLauncher,
mWorkspace, mNewScale)); mWorkspace, mNewScale, WORKSPACE_SCALE_PROPERTY));
} else { } else {
propertySetter.setFloat(mWorkspace, WORKSPACE_STATE_SCALE_PROPERTY, mNewScale, propertySetter.setFloat(mWorkspace, WORKSPACE_SCALE_PROPERTY, mNewScale,
scaleInterpolator); scaleInterpolator);
} }
@@ -130,11 +134,12 @@ public class WorkspaceStateTransitionAnimation {
float hotseatScale = hotseatScaleAndTranslation.scale; float hotseatScale = hotseatScaleAndTranslation.scale;
if (shouldSpring) { if (shouldSpring) {
PendingAnimation pa = (PendingAnimation) propertySetter; PendingAnimation pa = (PendingAnimation) propertySetter;
pa.add(getSpringScaleAnimator(mLauncher, hotseat, hotseatScale)); pa.add(getSpringScaleAnimator(mLauncher, hotseat, hotseatScale,
HOTSEAT_SCALE_PROPERTY));
} else { } else {
Interpolator hotseatScaleInterpolator = config.getInterpolator(ANIM_HOTSEAT_SCALE, Interpolator hotseatScaleInterpolator = config.getInterpolator(ANIM_HOTSEAT_SCALE,
scaleInterpolator); scaleInterpolator);
propertySetter.setFloat(hotseat, WORKSPACE_STATE_SCALE_PROPERTY, hotseatScale, propertySetter.setFloat(hotseat, HOTSEAT_SCALE_PROPERTY, hotseatScale,
hotseatScaleInterpolator); hotseatScaleInterpolator);
} }
@@ -197,10 +202,19 @@ public class WorkspaceStateTransitionAnimation {
pageAlpha, fadeInterpolator); pageAlpha, fadeInterpolator);
} }
/**
* Returns a spring based animator for the scale property of {@param workspace}.
*/
public static ValueAnimator getWorkspaceSpringScaleAnimator(Launcher launcher,
Workspace workspace, float scale) {
return getSpringScaleAnimator(launcher, workspace, scale, WORKSPACE_SCALE_PROPERTY);
}
/** /**
* Returns a spring based animator for the scale property of {@param v}. * Returns a spring based animator for the scale property of {@param v}.
*/ */
public static ValueAnimator getSpringScaleAnimator(Launcher launcher, View v, float scale) { public static <T extends View> ValueAnimator getSpringScaleAnimator(Launcher launcher, T v,
float scale, FloatProperty<T> property) {
ResourceProvider rp = DynamicResource.provider(launcher); ResourceProvider rp = DynamicResource.provider(launcher);
float damping = rp.getFloat(R.dimen.hint_scale_damping_ratio); float damping = rp.getFloat(R.dimen.hint_scale_damping_ratio);
float stiffness = rp.getFloat(R.dimen.hint_scale_stiffness); float stiffness = rp.getFloat(R.dimen.hint_scale_stiffness);
@@ -211,9 +225,9 @@ public class WorkspaceStateTransitionAnimation {
.setDampingRatio(damping) .setDampingRatio(damping)
.setMinimumVisibleChange(MIN_VISIBLE_CHANGE_SCALE) .setMinimumVisibleChange(MIN_VISIBLE_CHANGE_SCALE)
.setEndValue(scale) .setEndValue(scale)
.setStartValue(WORKSPACE_STATE_SCALE_PROPERTY.get(v)) .setStartValue(property.get(v))
.setStartVelocity(velocityPxPerS) .setStartVelocity(velocityPxPerS)
.build(v, WORKSPACE_STATE_SCALE_PROPERTY); .build(v, property);
} }
} }
@@ -18,6 +18,8 @@ package com.android.launcher3.util;
import android.util.ArrayMap; import android.util.ArrayMap;
import android.util.FloatProperty; import android.util.FloatProperty;
import android.util.Log;
import android.view.View;
import com.android.launcher3.Utilities; import com.android.launcher3.Utilities;
@@ -33,8 +35,10 @@ import com.android.launcher3.Utilities;
* *
* @param <T> Type where to apply the property. * @param <T> Type where to apply the property.
*/ */
public abstract class MultiScalePropertyFactory<T> { public class MultiScalePropertyFactory<T extends View> {
private static final boolean DEBUG = false;
private static final String TAG = "MultiScaleProperty";
private final String mName; private final String mName;
private final ArrayMap<Integer, MultiScaleProperty> mProperties = private final ArrayMap<Integer, MultiScaleProperty> mProperties =
new ArrayMap<Integer, MultiScaleProperty>(); new ArrayMap<Integer, MultiScaleProperty>();
@@ -56,7 +60,6 @@ public abstract class MultiScalePropertyFactory<T> {
(k) -> new MultiScaleProperty(index, mName + "_" + index)); (k) -> new MultiScaleProperty(index, mName + "_" + index));
} }
/** /**
* Each [setValue] will be aggregated with the other properties values created by the * Each [setValue] will be aggregated with the other properties values created by the
* corresponding factory. * corresponding factory.
@@ -91,11 +94,22 @@ public abstract class MultiScalePropertyFactory<T> {
mLastAggregatedValue = Utilities.boundToRange(multValue, minValue, maxValue); mLastAggregatedValue = Utilities.boundToRange(multValue, minValue, maxValue);
mValue = newValue; mValue = newValue;
apply(obj, mLastAggregatedValue); apply(obj, mLastAggregatedValue);
if (DEBUG) {
Log.d(TAG, "name=" + mName
+ " newValue=" + newValue + " mInx=" + mInx
+ " aggregated=" + mLastAggregatedValue + " others= " + mProperties);
}
} }
@Override @Override
public Float get(T t) { public Float get(T view) {
return mLastAggregatedValue; // The scale of the view should match mLastAggregatedValue. Still, if it has been
// changed without using this property, it can differ. As this get method is usually
// used to set the starting point on an animation, this would result in some jumps
// when the view scale is different than the last aggregated value. To stay on the
// safe side, let's return the real view scale.
return view.getScaleX();
} }
@Override @Override
@@ -104,6 +118,8 @@ public abstract class MultiScalePropertyFactory<T> {
} }
} }
/** Applies value to object after setValue method is called. */ protected void apply(View view, float value) {
protected abstract void apply(T obj, float value); view.setScaleX(value);
view.setScaleY(value);
}
} }
@@ -1,5 +1,6 @@
package com.android.launcher3.util package com.android.launcher3.util
import android.view.View
import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
import com.google.common.truth.Truth.assertThat import com.google.common.truth.Truth.assertThat
@@ -14,8 +15,8 @@ class MultiScalePropertyTest {
private val received = mutableListOf<Float>() private val received = mutableListOf<Float>()
private val factory = private val factory =
object : MultiScalePropertyFactory<Int?>("Test") { object : MultiScalePropertyFactory<View?>("Test") {
override fun apply(obj: Int?, value: Float) { override fun apply(obj: View?, value: Float) {
received.add(value) received.add(value)
} }
} }