Merge "Adding support for skipping animation cancel on reapply" into main

This commit is contained in:
Fengjiang Li
2024-01-10 02:28:19 +00:00
committed by Android (Google) Code Review
7 changed files with 63 additions and 34 deletions
@@ -106,7 +106,7 @@ public class PortraitStatesTouchController extends AbstractStateChangeTouchContr
protected StateAnimationConfig getConfigForStates(
LauncherState fromState, LauncherState toState) {
final StateAnimationConfig config = new StateAnimationConfig();
config.userControlled = true;
config.animProps |= StateAnimationConfig.USER_CONTROLLED;
if (fromState == NORMAL && toState == ALL_APPS) {
AllAppsSwipeController.applyNormalToAllAppsAnimConfig(mLauncher, config);
} else if (fromState == ALL_APPS && toState == NORMAL) {
@@ -342,7 +342,7 @@ public class AllAppsTransitionController
});
}
if(FeatureFlags.ENABLE_PREMIUM_HAPTICS_ALL_APPS.get() && config.userControlled
if (FeatureFlags.ENABLE_PREMIUM_HAPTICS_ALL_APPS.get() && config.isUserControlled()
&& Utilities.ATLEAST_S) {
if (toState == ALL_APPS) {
builder.addOnFrameListener(
@@ -367,7 +367,7 @@ public class AllAppsTransitionController
// need to decide depending on the release velocity
Interpolator verticalProgressInterpolator = config.getInterpolator(ANIM_VERTICAL_PROGRESS,
config.userControlled ? LINEAR : DECELERATE_1_7);
config.isUserControlled() ? LINEAR : DECELERATE_1_7);
Animator anim = createSpringAnimation(mProgress, targetProgress);
anim.setInterpolator(verticalProgressInterpolator);
builder.add(anim);
@@ -19,6 +19,7 @@ package com.android.launcher3.statemanager;
import static android.animation.ValueAnimator.areAnimatorsEnabled;
import static com.android.launcher3.anim.AnimatorPlaybackController.callListenerCommandRecursively;
import static com.android.launcher3.states.StateAnimationConfig.HANDLE_STATE_APPLY;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_ALL_ANIMATIONS;
import android.animation.Animator;
@@ -36,6 +37,7 @@ import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
import com.android.launcher3.states.StateAnimationConfig.AnimationPropertyFlags;
import com.android.launcher3.testing.shared.TestProtocol;
import java.io.PrintWriter;
@@ -189,7 +191,7 @@ public class StateManager<STATE_TYPE extends BaseState<STATE_TYPE>> {
public void reapplyState(boolean cancelCurrentAnimation) {
boolean wasInAnimation = mConfig.currentAnimation != null;
if (cancelCurrentAnimation) {
if (cancelCurrentAnimation && (mConfig.animProps & HANDLE_STATE_APPLY) == 0) {
// Animation canceling can trigger a cleanup routine, causing problems when we are in a
// launcher state that relies on member variable data. So if we are in one of those
// states, accelerate the current animation to its end point rather than canceling it
@@ -237,7 +239,7 @@ public class StateManager<STATE_TYPE extends BaseState<STATE_TYPE>> {
listener.onAnimationEnd(null);
}
return;
} else if ((!mConfig.userControlled && animated && mConfig.targetState == state)
} else if ((!mConfig.isUserControlled() && animated && mConfig.targetState == state)
|| mState.shouldPreserveDataStateOnReapply()) {
// We are running the same animation as requested, and/or target state should not be
// reset -- allow the current animation to complete instead of canceling it.
@@ -343,7 +345,7 @@ public class StateManager<STATE_TYPE extends BaseState<STATE_TYPE>> {
public AnimatorPlaybackController createAnimationToNewWorkspace(STATE_TYPE state,
StateAnimationConfig config) {
config.userControlled = true;
config.animProps |= StateAnimationConfig.USER_CONTROLLED;
cancelAnimation();
config.copyTo(mConfig);
mConfig.playbackController = createAnimationToNewWorkspaceInternal(state)
@@ -418,7 +420,7 @@ public class StateManager<STATE_TYPE extends BaseState<STATE_TYPE>> {
}
public void moveToRestState(boolean isAnimated) {
if (mConfig.currentAnimation != null && mConfig.userControlled) {
if (mConfig.currentAnimation != null && mConfig.isUserControlled()) {
// The user is doing something. Lets not mess it up
return;
}
@@ -450,10 +452,18 @@ public class StateManager<STATE_TYPE extends BaseState<STATE_TYPE>> {
}
}
/**
* Sets the provided controller as the current user controlled state animation
*/
public void setCurrentUserControlledAnimation(AnimatorPlaybackController controller) {
setCurrentAnimation(controller, StateAnimationConfig.USER_CONTROLLED);
}
public void setCurrentAnimation(AnimatorPlaybackController controller,
@AnimationPropertyFlags int animationProps) {
clearCurrentAnimation();
setCurrentAnimation(controller.getTarget());
mConfig.userControlled = true;
mConfig.animProps = animationProps;
mConfig.playbackController = controller;
}
@@ -126,16 +126,8 @@ public abstract class StatefulActivity<STATE_TYPE extends BaseState<STATE_TYPE>>
@Override
public void reapplyUi() {
reapplyUi(true /* cancelCurrentAnimation */);
}
/**
* Re-applies if any state transition is not running, optionally cancelling
* the transition if requested.
*/
public void reapplyUi(boolean cancelCurrentAnimation) {
getRootView().dispatchInsets();
getStateManager().reapplyState(cancelCurrentAnimation);
getStateManager().reapplyState(true /* cancelCurrentAnimation */);
}
@Override
@@ -40,8 +40,19 @@ public class StateAnimationConfig {
public static final int SKIP_DEPTH_CONTROLLER = 1 << 2;
public static final int SKIP_SCRIM = 1 << 3;
@IntDef(flag = true, value = {
USER_CONTROLLED,
HANDLE_STATE_APPLY
})
@Retention(RetentionPolicy.SOURCE)
public @interface AnimationPropertyFlags {}
// Indicates that the animation is controlled by the user
public static final int USER_CONTROLLED = 1 << 0;
// Indicates that he animation can survive state UI resets due to inset or config changes
public static final int HANDLE_STATE_APPLY = 1 << 1;
public long duration;
public boolean userControlled;
public @AnimationPropertyFlags int animProps = 0;
public @AnimationFlags int animFlags = 0;
@@ -105,12 +116,16 @@ public class StateAnimationConfig {
public void copyTo(StateAnimationConfig target) {
target.duration = duration;
target.animFlags = animFlags;
target.userControlled = userControlled;
target.animProps = animProps;
for (int i = 0; i < ANIM_TYPES_COUNT; i++) {
target.mInterpolators[i] = mInterpolators[i];
}
}
public boolean isUserControlled() {
return (animProps & USER_CONTROLLED) != 0;
}
/**
* Returns the interpolator set for animId or fallback if nothing is set
*
@@ -192,7 +192,7 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController {
protected StateAnimationConfig getConfigForStates(LauncherState fromState,
LauncherState toState) {
StateAnimationConfig config = super.getConfigForStates(fromState, toState);
config.userControlled = true;
config.animProps |= StateAnimationConfig.USER_CONTROLLED;
if (fromState == NORMAL && toState == ALL_APPS) {
applyNormalToAllAppsAnimConfig(mLauncher, config);
} else if (fromState == ALL_APPS && toState == NORMAL) {
@@ -209,13 +209,13 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController {
config.setInterpolator(ANIM_SCRIM_FADE,
Interpolators.reverse(ALL_APPS_SCRIM_RESPONDER));
config.setInterpolator(ANIM_ALL_APPS_FADE, FINAL_FRAME);
if (!config.userControlled) {
if (!config.isUserControlled()) {
config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED);
}
config.setInterpolator(ANIM_WORKSPACE_SCALE, DECELERATED_EASE);
config.setInterpolator(ANIM_DEPTH, DECELERATED_EASE);
} else {
if (config.userControlled) {
if (config.isUserControlled()) {
config.setInterpolator(ANIM_DEPTH, Interpolators.reverse(BLUR_MANUAL));
config.setInterpolator(ANIM_WORKSPACE_FADE,
Interpolators.reverse(WORKSPACE_FADE_MANUAL));
@@ -250,29 +250,32 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController {
if (launcher.getDeviceProfile().isTablet) {
config.setInterpolator(ANIM_ALL_APPS_FADE, INSTANT);
config.setInterpolator(ANIM_SCRIM_FADE, ALL_APPS_SCRIM_RESPONDER);
if (!config.userControlled) {
if (!config.isUserControlled()) {
config.setInterpolator(ANIM_VERTICAL_PROGRESS, EMPHASIZED);
}
config.setInterpolator(ANIM_WORKSPACE_SCALE, DECELERATED_EASE);
config.setInterpolator(ANIM_DEPTH, DECELERATED_EASE);
} else {
config.setInterpolator(ANIM_DEPTH, config.userControlled ? BLUR_MANUAL : BLUR_ATOMIC);
config.setInterpolator(ANIM_DEPTH,
config.isUserControlled() ? BLUR_MANUAL : BLUR_ATOMIC);
config.setInterpolator(ANIM_WORKSPACE_FADE,
config.userControlled ? WORKSPACE_FADE_MANUAL : WORKSPACE_FADE_ATOMIC);
config.isUserControlled() ? WORKSPACE_FADE_MANUAL : WORKSPACE_FADE_ATOMIC);
config.setInterpolator(ANIM_WORKSPACE_SCALE,
config.userControlled ? WORKSPACE_SCALE_MANUAL : WORKSPACE_SCALE_ATOMIC);
config.isUserControlled() ? WORKSPACE_SCALE_MANUAL : WORKSPACE_SCALE_ATOMIC);
config.setInterpolator(ANIM_HOTSEAT_FADE,
config.userControlled ? HOTSEAT_FADE_MANUAL : HOTSEAT_FADE_ATOMIC);
config.isUserControlled() ? HOTSEAT_FADE_MANUAL : HOTSEAT_FADE_ATOMIC);
config.setInterpolator(ANIM_HOTSEAT_SCALE,
config.userControlled ? HOTSEAT_SCALE_MANUAL : HOTSEAT_SCALE_ATOMIC);
config.isUserControlled() ? HOTSEAT_SCALE_MANUAL : HOTSEAT_SCALE_ATOMIC);
config.setInterpolator(ANIM_HOTSEAT_TRANSLATE,
config.userControlled ? HOTSEAT_TRANSLATE_MANUAL : HOTSEAT_TRANSLATE_ATOMIC);
config.isUserControlled()
? HOTSEAT_TRANSLATE_MANUAL
: HOTSEAT_TRANSLATE_ATOMIC);
config.setInterpolator(ANIM_SCRIM_FADE,
config.userControlled ? SCRIM_FADE_MANUAL : SCRIM_FADE_ATOMIC);
config.isUserControlled() ? SCRIM_FADE_MANUAL : SCRIM_FADE_ATOMIC);
config.setInterpolator(ANIM_ALL_APPS_FADE,
config.userControlled ? ALL_APPS_FADE_MANUAL : ALL_APPS_FADE_ATOMIC);
config.isUserControlled() ? ALL_APPS_FADE_MANUAL : ALL_APPS_FADE_ATOMIC);
config.setInterpolator(ANIM_VERTICAL_PROGRESS,
config.userControlled
config.isUserControlled()
? ALL_APPS_VERTICAL_PROGRESS_MANUAL
: ALL_APPS_VERTICAL_PROGRESS_ATOMIC);
}
@@ -285,7 +288,7 @@ public class AllAppsSwipeController extends AbstractStateChangeTouchController {
*/
public static void applyOverviewToAllAppsAnimConfig(
DeviceProfile deviceProfile, StateAnimationConfig config, float threshold) {
config.userControlled = true;
config.animProps |= StateAnimationConfig.USER_CONTROLLED;
config.animFlags = SKIP_OVERVIEW;
if (deviceProfile.isTablet) {
config.setInterpolator(ANIM_ALL_APPS_FADE, INSTANT);
@@ -26,6 +26,8 @@ import com.android.launcher3.anim.AnimatorListeners
import com.android.launcher3.anim.AnimatorPlaybackController
import com.android.launcher3.anim.PendingAnimation
import com.android.launcher3.statemanager.StatefulActivity
import com.android.launcher3.states.StateAnimationConfig.HANDLE_STATE_APPLY
import com.android.launcher3.states.StateAnimationConfig.USER_CONTROLLED
import java.util.function.Consumer
private const val TAG = "CannedAnimCoordinator"
@@ -107,8 +109,15 @@ class CannedAnimationCoordinator(private val activity: StatefulActivity<*>) {
}
// Link this to the state manager so that it auto-cancels when state changes
recreatePending = false
// Animator coordinator takes care of reapplying the animation due to state reset. Set the
// flags accordingly
animationController =
controller.apply { activity.stateManager.setCurrentUserControlledAnimation(this) }
controller.apply {
activity.stateManager.setCurrentAnimation(
this,
USER_CONTROLLED or HANDLE_STATE_APPLY
)
}
recreateAnimation(provider)
}