diff --git a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java index 75cf5cb3a5..bd7e5de866 100644 --- a/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java +++ b/quickstep/src/com/android/launcher3/uioverrides/states/QuickstepAtomicAnimationFactory.java @@ -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.NORMAL; 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_DEACCEL; import static com.android.launcher3.anim.Interpolators.DEACCEL; @@ -172,7 +172,8 @@ public class QuickstepAtomicAnimationFactory extends } else if (fromState == HINT_STATE && toState == NORMAL) { config.setInterpolator(ANIM_DEPTH, DEACCEL_3); if (mHintToNormalDuration == -1) { - ValueAnimator va = getSpringScaleAnimator(mActivity, mActivity.getWorkspace(), + ValueAnimator va = getWorkspaceSpringScaleAnimator(mActivity, + mActivity.getWorkspace(), toState.getWorkspaceScaleAndTranslation(mActivity).scale); mHintToNormalDuration = (int) va.getDuration(); } diff --git a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java index 333df10dde..3b5804634a 100644 --- a/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java +++ b/quickstep/src/com/android/quickstep/util/LauncherUnfoldAnimationController.java @@ -15,14 +15,14 @@ */ 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_PROPERTY_FACTORY; +import static com.android.launcher3.LauncherAnimUtils.WORKSPACE_SCALE_PROPERTY_FACTORY; import static com.android.launcher3.Utilities.comp; import android.annotation.Nullable; import android.util.FloatProperty; import android.util.MathUtils; -import android.view.View; import android.view.WindowManager; import android.view.WindowManagerGlobal; @@ -30,6 +30,7 @@ import androidx.core.view.OneShotPreDrawListener; import com.android.launcher3.Hotseat; import com.android.launcher3.Launcher; +import com.android.launcher3.Workspace; import com.android.launcher3.util.HorizontalInsettableView; import com.android.systemui.unfold.UnfoldTransitionProgressProvider; 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 // from the both sides of the bar when progress is 0 private static final float MAX_WIDTH_INSET_FRACTION = 0.15f; - private static final FloatProperty UNFOLD_SCALE_PROPERTY = - SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION); + private static final FloatProperty WORKSPACE_SCALE_PROPERTY = + WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION); + private static final FloatProperty HOTSEAT_SCALE_PROPERTY = + HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_UNFOLD_ANIMATION); private final Launcher mLauncher; @@ -147,8 +150,8 @@ public class LauncherUnfoldAnimationController { } private void setScale(float value) { - UNFOLD_SCALE_PROPERTY.setValue(mLauncher.getWorkspace(), value); - UNFOLD_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value); + WORKSPACE_SCALE_PROPERTY.setValue(mLauncher.getWorkspace(), value); + HOTSEAT_SCALE_PROPERTY.setValue(mLauncher.getHotseat(), value); } } } diff --git a/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java b/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java index 8659b687c3..5326d2bb66 100644 --- a/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java +++ b/quickstep/src/com/android/quickstep/util/WorkspaceRevealAnim.java @@ -15,8 +15,9 @@ */ 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_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.NORMAL; import static com.android.launcher3.anim.PropertySetter.NO_ANIM_PROPERTY_SETTER; @@ -32,6 +33,7 @@ import android.util.FloatProperty; import android.view.View; import com.android.launcher3.BaseQuickstepLauncher; +import com.android.launcher3.Hotseat; import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.Workspace; @@ -51,8 +53,11 @@ public class WorkspaceRevealAnim { // Should be used for animations running alongside this WorkspaceRevealAnim. public static final int DURATION_MS = 350; - private static final FloatProperty REVEAL_SCALE_PROPERTY = - SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_REVEAL_ANIM); + private static final FloatProperty WORKSPACE_SCALE_PROPERTY = + WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_REVEAL_ANIM); + + private static final FloatProperty HOTSEAT_SCALE_PROPERTY = + HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_REVEAL_ANIM); private final float mScaleStart; private final AnimatorSet mAnimators = new AnimatorSet(); @@ -67,8 +72,8 @@ public class WorkspaceRevealAnim { workspace.setPivotToScaleWithSelf(launcher.getHotseat()); // Add reveal animations. - addRevealAnimatorsForView(workspace); - addRevealAnimatorsForView(launcher.getHotseat()); + addRevealAnimatorsForView(workspace, WORKSPACE_SCALE_PROPERTY); + addRevealAnimatorsForView(launcher.getHotseat(), HOTSEAT_SCALE_PROPERTY); // Add overview scrim animation. if (animateOverviewScrim) { @@ -93,8 +98,8 @@ public class WorkspaceRevealAnim { mAnimators.setInterpolator(Interpolators.DECELERATED_EASE); } - private void addRevealAnimatorsForView(View v) { - ObjectAnimator scale = ObjectAnimator.ofFloat(v, REVEAL_SCALE_PROPERTY, mScaleStart, 1f); + private void addRevealAnimatorsForView(T v, FloatProperty scaleProperty) { + ObjectAnimator scale = ObjectAnimator.ofFloat(v, scaleProperty, mScaleStart, 1f); scale.setDuration(DURATION_MS); scale.setInterpolator(Interpolators.DECELERATED_EASE); mAnimators.play(scale); @@ -107,7 +112,7 @@ public class WorkspaceRevealAnim { mAnimators.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationEnd(Animator animation) { - REVEAL_SCALE_PROPERTY.set(v, 1f); + scaleProperty.set(v, 1f); v.setAlpha(1f); } }); diff --git a/src/com/android/launcher3/LauncherAnimUtils.java b/src/com/android/launcher3/LauncherAnimUtils.java index 430039276e..c43172cc56 100644 --- a/src/com/android/launcher3/LauncherAnimUtils.java +++ b/src/com/android/launcher3/LauncherAnimUtils.java @@ -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 * animation. */ - public static final MultiScalePropertyFactory SCALE_PROPERTY_FACTORY = - new MultiScalePropertyFactory("scale_property") { - @Override - protected void apply(View view, float scale) { - view.setScaleX(scale); - view.setScaleY(scale); - } - }; + public static final MultiScalePropertyFactory WORKSPACE_SCALE_PROPERTY_FACTORY = + new MultiScalePropertyFactory("workspace_scale_property"); + + /** Property to set the scale of hotseat. */ + public static final MultiScalePropertyFactory HOTSEAT_SCALE_PROPERTY_FACTORY = + new MultiScalePropertyFactory("hotseat_scale_property"); public static final int SCALE_INDEX_UNFOLD_ANIMATION = 1; public static final int SCALE_INDEX_UNLOCK_ANIMATION = 2; diff --git a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java index 98e785f47b..d94e84cbac 100644 --- a/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java +++ b/src/com/android/launcher3/WorkspaceStateTransitionAnimation.java @@ -18,11 +18,12 @@ package com.android.launcher3; 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_PROPERTY_FACTORY; 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_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.HINT_STATE; import static com.android.launcher3.LauncherState.HOTSEAT_ICONS; @@ -64,8 +65,11 @@ import com.android.systemui.plugins.ResourceProvider; */ public class WorkspaceStateTransitionAnimation { - private static final FloatProperty WORKSPACE_STATE_SCALE_PROPERTY = - SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_WORKSPACE_STATE); + private static final FloatProperty WORKSPACE_SCALE_PROPERTY = + WORKSPACE_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_WORKSPACE_STATE); + + private static final FloatProperty HOTSEAT_SCALE_PROPERTY = + HOTSEAT_SCALE_PROPERTY_FACTORY.get(SCALE_INDEX_WORKSPACE_STATE); private final Launcher mLauncher; private final Workspace mWorkspace; @@ -120,9 +124,9 @@ public class WorkspaceStateTransitionAnimation { && fromState == HINT_STATE && state == NORMAL; if (shouldSpring) { ((PendingAnimation) propertySetter).add(getSpringScaleAnimator(mLauncher, - mWorkspace, mNewScale)); + mWorkspace, mNewScale, WORKSPACE_SCALE_PROPERTY)); } else { - propertySetter.setFloat(mWorkspace, WORKSPACE_STATE_SCALE_PROPERTY, mNewScale, + propertySetter.setFloat(mWorkspace, WORKSPACE_SCALE_PROPERTY, mNewScale, scaleInterpolator); } @@ -130,11 +134,12 @@ public class WorkspaceStateTransitionAnimation { float hotseatScale = hotseatScaleAndTranslation.scale; if (shouldSpring) { PendingAnimation pa = (PendingAnimation) propertySetter; - pa.add(getSpringScaleAnimator(mLauncher, hotseat, hotseatScale)); + pa.add(getSpringScaleAnimator(mLauncher, hotseat, hotseatScale, + HOTSEAT_SCALE_PROPERTY)); } else { Interpolator hotseatScaleInterpolator = config.getInterpolator(ANIM_HOTSEAT_SCALE, scaleInterpolator); - propertySetter.setFloat(hotseat, WORKSPACE_STATE_SCALE_PROPERTY, hotseatScale, + propertySetter.setFloat(hotseat, HOTSEAT_SCALE_PROPERTY, hotseatScale, hotseatScaleInterpolator); } @@ -197,10 +202,19 @@ public class WorkspaceStateTransitionAnimation { 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}. */ - public static ValueAnimator getSpringScaleAnimator(Launcher launcher, View v, float scale) { + public static ValueAnimator getSpringScaleAnimator(Launcher launcher, T v, + float scale, FloatProperty property) { ResourceProvider rp = DynamicResource.provider(launcher); float damping = rp.getFloat(R.dimen.hint_scale_damping_ratio); float stiffness = rp.getFloat(R.dimen.hint_scale_stiffness); @@ -211,9 +225,9 @@ public class WorkspaceStateTransitionAnimation { .setDampingRatio(damping) .setMinimumVisibleChange(MIN_VISIBLE_CHANGE_SCALE) .setEndValue(scale) - .setStartValue(WORKSPACE_STATE_SCALE_PROPERTY.get(v)) + .setStartValue(property.get(v)) .setStartVelocity(velocityPxPerS) - .build(v, WORKSPACE_STATE_SCALE_PROPERTY); + .build(v, property); } } \ No newline at end of file diff --git a/src/com/android/launcher3/util/MultiScalePropertyFactory.java b/src/com/android/launcher3/util/MultiScalePropertyFactory.java index f27d0f0d86..a7e6cc8679 100644 --- a/src/com/android/launcher3/util/MultiScalePropertyFactory.java +++ b/src/com/android/launcher3/util/MultiScalePropertyFactory.java @@ -18,6 +18,8 @@ package com.android.launcher3.util; import android.util.ArrayMap; import android.util.FloatProperty; +import android.util.Log; +import android.view.View; import com.android.launcher3.Utilities; @@ -33,8 +35,10 @@ import com.android.launcher3.Utilities; * * @param Type where to apply the property. */ -public abstract class MultiScalePropertyFactory { +public class MultiScalePropertyFactory { + private static final boolean DEBUG = false; + private static final String TAG = "MultiScaleProperty"; private final String mName; private final ArrayMap mProperties = new ArrayMap(); @@ -56,7 +60,6 @@ public abstract class MultiScalePropertyFactory { (k) -> new MultiScaleProperty(index, mName + "_" + index)); } - /** * Each [setValue] will be aggregated with the other properties values created by the * corresponding factory. @@ -91,11 +94,22 @@ public abstract class MultiScalePropertyFactory { mLastAggregatedValue = Utilities.boundToRange(multValue, minValue, maxValue); mValue = newValue; apply(obj, mLastAggregatedValue); + + if (DEBUG) { + Log.d(TAG, "name=" + mName + + " newValue=" + newValue + " mInx=" + mInx + + " aggregated=" + mLastAggregatedValue + " others= " + mProperties); + } } @Override - public Float get(T t) { - return mLastAggregatedValue; + public Float get(T view) { + // 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 @@ -104,6 +118,8 @@ public abstract class MultiScalePropertyFactory { } } - /** Applies value to object after setValue method is called. */ - protected abstract void apply(T obj, float value); + protected void apply(View view, float value) { + view.setScaleX(value); + view.setScaleY(value); + } } diff --git a/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt b/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt index c4a8db6adf..6099987172 100644 --- a/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt +++ b/tests/src/com/android/launcher3/util/MultiScalePropertyTest.kt @@ -1,5 +1,6 @@ package com.android.launcher3.util +import android.view.View import androidx.test.ext.junit.runners.AndroidJUnit4 import androidx.test.filters.SmallTest import com.google.common.truth.Truth.assertThat @@ -14,8 +15,8 @@ class MultiScalePropertyTest { private val received = mutableListOf() private val factory = - object : MultiScalePropertyFactory("Test") { - override fun apply(obj: Int?, value: Float) { + object : MultiScalePropertyFactory("Test") { + override fun apply(obj: View?, value: Float) { received.add(value) } }