Remove Overview atomic animation support

- Remove PLAY_ATOMIC_OVERVIEW_SCALE and PLAY_ATOMIC_OVERVIEW_PEEK
- Remove complicated parallel atomic animation support from
  AbstractStateChangeTouchController and subclasses
- Remove some code related to going between Overview <-> AllApps

Test: Swipe between states in all 3 navigation modes
Bug: 175137718
Change-Id: Ice314d46946c3a983cdc6ccf1a67effb5da9156e
This commit is contained in:
Tony Wickham
2021-03-23 17:22:28 -07:00
parent c5d168da82
commit 6cd95cd2d8
17 changed files with 62 additions and 450 deletions

View File

@@ -27,30 +27,20 @@ import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEDOWN;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEUP;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_ALL_COMPONENTS;
import static com.android.launcher3.states.StateAnimationConfig.PLAY_ATOMIC_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.PLAY_NON_ATOMIC;
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
import android.animation.Animator;
import android.animation.Animator.AnimatorListener;
import android.animation.AnimatorListenerAdapter;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.os.SystemClock;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherAnimUtils;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.logger.LauncherAtom;
import com.android.launcher3.logging.StatsLogManager;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.launcher3.states.StateAnimationConfig.AnimationFlags;
import com.android.launcher3.util.FlingBlockCheck;
import com.android.launcher3.util.TouchController;
@@ -60,13 +50,6 @@ import com.android.launcher3.util.TouchController;
public abstract class AbstractStateChangeTouchController
implements TouchController, SingleAxisSwipeDetector.Listener {
/**
* Play an atomic recents animation when the progress from NORMAL to OVERVIEW reaches this.
* TODO: Remove the atomic animation altogether and just go to OVERVIEW directly (b/175137718).
*/
public static final float ATOMIC_OVERVIEW_ANIM_THRESHOLD = 1f;
protected final long ATOMIC_DURATION = getAtomicDuration();
protected final Launcher mLauncher;
protected final SingleAxisSwipeDetector mDetector;
protected final SingleAxisSwipeDetector.Direction mSwipeDirection;
@@ -89,23 +72,7 @@ public abstract class AbstractStateChangeTouchController
private float mProgressMultiplier;
private float mDisplacementShift;
private boolean mCanBlockFling;
private FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
protected AnimatorSet mAtomicAnim;
// True if we want to resume playing atomic components when mAtomicAnim completes.
private boolean mScheduleResumeAtomicComponent;
private AutoPlayAtomicAnimationInfo mAtomicAnimAutoPlayInfo;
private boolean mPassedOverviewAtomicThreshold;
// mAtomicAnim plays the atomic components of the state animations when we pass the threshold.
// However, if we reinit to transition to a new state (e.g. OVERVIEW -> ALL_APPS) before the
// atomic animation finishes, we only control the non-atomic components so that we don't
// interfere with the atomic animation. When the atomic animation ends, we start controlling
// the atomic components as well, using this controller.
private AnimatorPlaybackController mAtomicComponentsController;
private LauncherState mAtomicComponentsTargetState = NORMAL;
private float mAtomicComponentsStartProgress;
private final FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
public AbstractStateChangeTouchController(Launcher l, SingleAxisSwipeDetector.Direction dir) {
mLauncher = l;
@@ -113,10 +80,6 @@ public abstract class AbstractStateChangeTouchController
mSwipeDirection = dir;
}
protected long getAtomicDuration() {
return 200;
}
protected abstract boolean canInterceptTouch(MotionEvent ev);
@Override
@@ -182,7 +145,7 @@ public abstract class AbstractStateChangeTouchController
protected abstract LauncherState getTargetState(LauncherState fromState,
boolean isDragTowardPositive);
protected abstract float initCurrentAnimation(@AnimationFlags int animComponents);
protected abstract float initCurrentAnimation();
private boolean reinitCurrentAnimation(boolean reachedToState, boolean isDragTowardPositive) {
LauncherState newFromState = mFromState == null ? mLauncher.getStateManager().getState()
@@ -199,28 +162,10 @@ public abstract class AbstractStateChangeTouchController
mToState = newToState;
mStartProgress = 0;
mPassedOverviewAtomicThreshold = false;
if (mCurrentAnimation != null) {
mCurrentAnimation.getTarget().removeListener(mClearStateOnCancelListener);
}
int animComponents = goingBetweenNormalAndOverview(mFromState, mToState)
? PLAY_NON_ATOMIC : ANIM_ALL_COMPONENTS;
mScheduleResumeAtomicComponent = false;
if (mAtomicAnim != null) {
animComponents = PLAY_NON_ATOMIC;
// Control the non-atomic components until the atomic animation finishes, then control
// the atomic components as well.
mScheduleResumeAtomicComponent = true;
}
if (goingBetweenNormalAndOverview(mFromState, mToState)
|| mAtomicComponentsTargetState != mToState) {
cancelAtomicComponentsController();
}
if (mAtomicComponentsController != null) {
animComponents &= ~PLAY_ATOMIC_OVERVIEW_SCALE;
}
mProgressMultiplier = initCurrentAnimation(animComponents);
mProgressMultiplier = initCurrentAnimation();
mCurrentAnimation.dispatchOnStart();
return true;
}
@@ -231,13 +176,6 @@ public abstract class AbstractStateChangeTouchController
protected void onReachedFinalState(LauncherState newToState) {
}
protected boolean goingBetweenNormalAndOverview(LauncherState fromState,
LauncherState toState) {
return (fromState == NORMAL || fromState == OVERVIEW)
&& (toState == NORMAL || toState == OVERVIEW)
&& mGoingBetweenStates;
}
@Override
public void onDragStart(boolean start, float startDisplacement) {
mStartState = mLauncher.getStateManager().getState();
@@ -252,11 +190,6 @@ public abstract class AbstractStateChangeTouchController
} else {
mCurrentAnimation.pause();
mStartProgress = mCurrentAnimation.getProgressFraction();
mAtomicAnimAutoPlayInfo = null;
if (mAtomicComponentsController != null) {
mAtomicComponentsController.pause();
}
}
mCanBlockFling = mFromState == NORMAL;
mFlingBlockCheck.unblockFling();
@@ -310,69 +243,6 @@ public abstract class AbstractStateChangeTouchController
return;
}
mCurrentAnimation.setPlayFraction(fraction);
if (mAtomicComponentsController != null) {
// Make sure we don't divide by 0, and have at least a small runway.
float start = Math.min(mAtomicComponentsStartProgress, 0.9f);
mAtomicComponentsController.setPlayFraction((fraction - start) / (1 - start));
}
maybeUpdateAtomicAnim(mFromState, mToState, fraction);
}
/**
* When going between normal and overview states, see if we passed the overview threshold and
* play the appropriate atomic animation if so.
*/
private void maybeUpdateAtomicAnim(LauncherState fromState, LauncherState toState,
float progress) {
if (!goingBetweenNormalAndOverview(fromState, toState)) {
return;
}
boolean passedThreshold = progress >= ATOMIC_OVERVIEW_ANIM_THRESHOLD;
if (passedThreshold != mPassedOverviewAtomicThreshold) {
LauncherState atomicFromState = passedThreshold ? fromState: toState;
LauncherState atomicToState = passedThreshold ? toState : fromState;
mPassedOverviewAtomicThreshold = passedThreshold;
if (mAtomicAnim != null) {
mAtomicAnim.cancel();
}
mAtomicAnim = createAtomicAnimForState(atomicFromState, atomicToState, ATOMIC_DURATION);
mAtomicAnim.addListener(new AnimationSuccessListener() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
mAtomicAnim = null;
mScheduleResumeAtomicComponent = false;
}
@Override
public void onAnimationSuccess(Animator animator) {
if (!mScheduleResumeAtomicComponent) {
return;
}
cancelAtomicComponentsController();
if (mCurrentAnimation != null) {
mAtomicComponentsStartProgress = mCurrentAnimation.getProgressFraction();
long duration = (long) (getShiftRange() * 2);
mAtomicComponentsController = AnimatorPlaybackController.wrap(
createAtomicAnimForState(mFromState, mToState, duration), duration);
mAtomicComponentsController.dispatchOnStart();
mAtomicComponentsTargetState = mToState;
maybeAutoPlayAtomicComponentsAnim();
}
}
});
mAtomicAnim.start();
mLauncher.getDragLayer().performHapticFeedback(HapticFeedbackConstants.VIRTUAL_KEY);
}
}
private AnimatorSet createAtomicAnimForState(LauncherState fromState, LauncherState targetState,
long duration) {
StateAnimationConfig config = getConfigForStates(fromState, targetState);
config.animFlags = PLAY_ATOMIC_OVERVIEW_SCALE;
config.duration = duration;
return mLauncher.getStateManager().createAtomicAnimation(fromState, targetState, config);
}
/**
@@ -451,59 +321,12 @@ public abstract class AbstractStateChangeTouchController
mCurrentAnimation.setEndAction(() -> onSwipeInteractionCompleted(targetState));
ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
anim.setFloatValues(startProgress, endProgress);
maybeUpdateAtomicAnim(mFromState, targetState, targetState == mToState ? 1f : 0f);
updateSwipeCompleteAnimation(anim, Math.max(duration, getRemainingAtomicDuration()),
targetState, velocity, fling);
updateSwipeCompleteAnimation(anim, duration, targetState, velocity, fling);
mCurrentAnimation.dispatchOnStart();
if (fling && targetState == LauncherState.ALL_APPS && !UNSTABLE_SPRINGS.get()) {
mLauncher.getAppsView().addSpringFromFlingUpdateListener(anim, velocity);
}
anim.start();
mAtomicAnimAutoPlayInfo = new AutoPlayAtomicAnimationInfo(endProgress, anim.getDuration());
maybeAutoPlayAtomicComponentsAnim();
}
/**
* Animates the atomic components from the current progress to the final progress.
*
* Note that this only applies when we are controlling the atomic components separately from
* the non-atomic components, which only happens if we reinit before the atomic animation
* finishes.
*/
private void maybeAutoPlayAtomicComponentsAnim() {
if (mAtomicComponentsController == null || mAtomicAnimAutoPlayInfo == null) {
return;
}
final AnimatorPlaybackController controller = mAtomicComponentsController;
ValueAnimator atomicAnim = controller.getAnimationPlayer();
atomicAnim.setFloatValues(controller.getProgressFraction(),
mAtomicAnimAutoPlayInfo.toProgress);
long duration = mAtomicAnimAutoPlayInfo.endTime - SystemClock.elapsedRealtime();
mAtomicAnimAutoPlayInfo = null;
if (duration <= 0) {
atomicAnim.start();
atomicAnim.end();
mAtomicComponentsController = null;
} else {
atomicAnim.setDuration(duration);
atomicAnim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
if (mAtomicComponentsController == controller) {
mAtomicComponentsController = null;
}
}
});
atomicAnim.start();
}
}
private long getRemainingAtomicDuration() {
if (mAtomicAnim == null) {
return 0;
}
return mAtomicAnim.getTotalDuration() - mAtomicAnim.getCurrentPlayTime();
}
protected void updateSwipeCompleteAnimation(ValueAnimator animator, long expectedDuration,
@@ -513,10 +336,6 @@ public abstract class AbstractStateChangeTouchController
}
protected void onSwipeInteractionCompleted(LauncherState targetState) {
if (mAtomicComponentsController != null) {
mAtomicComponentsController.getAnimationPlayer().end();
mAtomicComponentsController = null;
}
onReachedFinalState(mToState);
clearState();
boolean shouldGoToTargetState = mGoingBetweenStates || (mToState != targetState);
@@ -556,37 +375,12 @@ public abstract class AbstractStateChangeTouchController
protected void clearState() {
cancelAnimationControllers();
if (mAtomicAnim != null) {
mAtomicAnim.cancel();
mAtomicAnim = null;
}
mGoingBetweenStates = true;
mScheduleResumeAtomicComponent = false;
mDetector.finishedScrolling();
mDetector.setDetectableScrollConditions(0, false);
}
private void cancelAnimationControllers() {
mCurrentAnimation = null;
cancelAtomicComponentsController();
}
private void cancelAtomicComponentsController() {
if (mAtomicComponentsController != null) {
mAtomicComponentsController.getAnimationPlayer().cancel();
mAtomicComponentsController = null;
}
mAtomicAnimAutoPlayInfo = null;
}
private static class AutoPlayAtomicAnimationInfo {
public final float toProgress;
public final long endTime;
AutoPlayAtomicAnimationInfo(float toProgress, long duration) {
this.toProgress = toProgress;
this.endTime = duration + SystemClock.elapsedRealtime();
}
}
}