2017-10-27 11:05:26 -07:00
|
|
|
/*
|
2018-09-10 16:48:47 -07:00
|
|
|
* Copyright (C) 2018 The Android Open Source Project
|
2017-10-27 11:05:26 -07:00
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
*/
|
2018-03-14 17:51:49 -07:00
|
|
|
package com.android.launcher3.touch;
|
2017-10-27 11:05:26 -07:00
|
|
|
|
2020-10-21 15:42:05 -07:00
|
|
|
import static com.android.launcher3.LauncherAnimUtils.SUCCESS_TRANSITION_PROGRESS;
|
|
|
|
|
import static com.android.launcher3.LauncherAnimUtils.newCancelListener;
|
2018-04-24 13:42:59 -07:00
|
|
|
import static com.android.launcher3.LauncherState.ALL_APPS;
|
|
|
|
|
import static com.android.launcher3.LauncherState.NORMAL;
|
|
|
|
|
import static com.android.launcher3.LauncherState.OVERVIEW;
|
2017-10-27 11:05:26 -07:00
|
|
|
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
|
2020-02-10 12:18:42 -08:00
|
|
|
import static com.android.launcher3.config.FeatureFlags.UNSTABLE_SPRINGS;
|
2020-09-15 00:34:10 -07:00
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_ALLAPPS;
|
|
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_HOME;
|
|
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LAUNCHER_STATE_OVERVIEW;
|
2020-06-19 02:58:53 -07:00
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEDOWN;
|
|
|
|
|
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_UNKNOWN_SWIPEUP;
|
2020-08-11 12:06:49 -07:00
|
|
|
import static com.android.launcher3.util.DisplayController.getSingleFrameMs;
|
2017-10-27 11:05:26 -07:00
|
|
|
|
2020-10-21 15:42:05 -07:00
|
|
|
import android.animation.Animator.AnimatorListener;
|
2017-10-27 11:05:26 -07:00
|
|
|
import android.animation.ValueAnimator;
|
|
|
|
|
import android.view.MotionEvent;
|
|
|
|
|
|
2017-12-12 12:02:29 -08:00
|
|
|
import com.android.launcher3.Launcher;
|
2018-05-09 16:00:14 -07:00
|
|
|
import com.android.launcher3.LauncherAnimUtils;
|
2017-12-12 12:02:29 -08:00
|
|
|
import com.android.launcher3.LauncherState;
|
|
|
|
|
import com.android.launcher3.Utilities;
|
2017-10-27 11:05:26 -07:00
|
|
|
import com.android.launcher3.anim.AnimatorPlaybackController;
|
2020-06-19 02:58:53 -07:00
|
|
|
import com.android.launcher3.logger.LauncherAtom;
|
|
|
|
|
import com.android.launcher3.logging.StatsLogManager;
|
2020-03-13 13:01:33 -07:00
|
|
|
import com.android.launcher3.states.StateAnimationConfig;
|
2018-05-09 16:00:14 -07:00
|
|
|
import com.android.launcher3.util.FlingBlockCheck;
|
2018-04-27 12:33:24 -05:00
|
|
|
import com.android.launcher3.util.TouchController;
|
2017-10-27 11:05:26 -07:00
|
|
|
|
|
|
|
|
/**
|
2018-03-14 17:51:49 -07:00
|
|
|
* TouchController for handling state changes
|
2017-10-27 11:05:26 -07:00
|
|
|
*/
|
2018-04-27 12:33:24 -05:00
|
|
|
public abstract class AbstractStateChangeTouchController
|
2019-08-15 17:24:07 -07:00
|
|
|
implements TouchController, SingleAxisSwipeDetector.Listener {
|
2017-10-27 11:05:26 -07:00
|
|
|
|
2017-12-12 12:02:29 -08:00
|
|
|
protected final Launcher mLauncher;
|
2019-08-15 17:24:07 -07:00
|
|
|
protected final SingleAxisSwipeDetector mDetector;
|
|
|
|
|
protected final SingleAxisSwipeDetector.Direction mSwipeDirection;
|
2017-10-27 11:05:26 -07:00
|
|
|
|
2020-10-21 15:42:05 -07:00
|
|
|
protected final AnimatorListener mClearStateOnCancelListener =
|
|
|
|
|
newCancelListener(this::clearState);
|
|
|
|
|
|
2017-10-27 11:05:26 -07:00
|
|
|
private boolean mNoIntercept;
|
2019-07-30 15:08:50 -07:00
|
|
|
private boolean mIsLogContainerSet;
|
2018-03-14 17:51:49 -07:00
|
|
|
protected int mStartContainerType;
|
2017-10-27 11:05:26 -07:00
|
|
|
|
2018-05-22 14:09:29 -07:00
|
|
|
protected LauncherState mStartState;
|
2018-03-14 17:51:49 -07:00
|
|
|
protected LauncherState mFromState;
|
2018-02-16 03:23:38 +00:00
|
|
|
protected LauncherState mToState;
|
2018-03-14 17:51:49 -07:00
|
|
|
protected AnimatorPlaybackController mCurrentAnimation;
|
2020-10-21 15:42:05 -07:00
|
|
|
protected boolean mGoingBetweenStates = true;
|
2017-10-27 11:05:26 -07:00
|
|
|
|
|
|
|
|
private float mStartProgress;
|
|
|
|
|
// Ratio of transition process [0, 1] to drag displacement (px)
|
|
|
|
|
private float mProgressMultiplier;
|
2018-03-28 11:21:49 -07:00
|
|
|
private float mDisplacementShift;
|
2018-05-09 10:13:01 -07:00
|
|
|
private boolean mCanBlockFling;
|
2021-03-23 17:22:28 -07:00
|
|
|
private final FlingBlockCheck mFlingBlockCheck = new FlingBlockCheck();
|
2018-04-19 11:39:34 -07:00
|
|
|
|
2019-08-15 17:24:07 -07:00
|
|
|
public AbstractStateChangeTouchController(Launcher l, SingleAxisSwipeDetector.Direction dir) {
|
2017-10-27 11:05:26 -07:00
|
|
|
mLauncher = l;
|
2019-08-15 17:24:07 -07:00
|
|
|
mDetector = new SingleAxisSwipeDetector(l, this, dir);
|
2019-03-22 19:15:39 -05:00
|
|
|
mSwipeDirection = dir;
|
2017-10-27 11:05:26 -07:00
|
|
|
}
|
|
|
|
|
|
2018-03-14 17:51:49 -07:00
|
|
|
protected abstract boolean canInterceptTouch(MotionEvent ev);
|
2017-12-12 12:02:29 -08:00
|
|
|
|
2017-10-27 11:05:26 -07:00
|
|
|
@Override
|
2021-02-09 17:59:48 -08:00
|
|
|
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
|
2017-10-27 11:05:26 -07:00
|
|
|
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
|
|
|
|
mNoIntercept = !canInterceptTouch(ev);
|
|
|
|
|
if (mNoIntercept) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Now figure out which direction scroll events the controller will start
|
|
|
|
|
// calling the callbacks.
|
|
|
|
|
final int directionsToDetectScroll;
|
|
|
|
|
boolean ignoreSlopWhenSettling = false;
|
|
|
|
|
|
|
|
|
|
if (mCurrentAnimation != null) {
|
2019-08-15 17:24:07 -07:00
|
|
|
directionsToDetectScroll = SingleAxisSwipeDetector.DIRECTION_BOTH;
|
2018-04-19 11:39:34 -07:00
|
|
|
ignoreSlopWhenSettling = true;
|
2017-10-27 11:05:26 -07:00
|
|
|
} else {
|
2018-04-24 13:42:59 -07:00
|
|
|
directionsToDetectScroll = getSwipeDirection();
|
2018-03-14 17:51:49 -07:00
|
|
|
if (directionsToDetectScroll == 0) {
|
|
|
|
|
mNoIntercept = true;
|
|
|
|
|
return false;
|
|
|
|
|
}
|
2017-10-27 11:05:26 -07:00
|
|
|
}
|
|
|
|
|
mDetector.setDetectableScrollConditions(
|
|
|
|
|
directionsToDetectScroll, ignoreSlopWhenSettling);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mNoIntercept) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
onControllerTouchEvent(ev);
|
|
|
|
|
return mDetector.isDraggingOrSettling();
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-24 13:42:59 -07:00
|
|
|
private int getSwipeDirection() {
|
|
|
|
|
LauncherState fromState = mLauncher.getStateManager().getState();
|
|
|
|
|
int swipeDirection = 0;
|
|
|
|
|
if (getTargetState(fromState, true /* isDragTowardPositive */) != fromState) {
|
2019-08-15 17:24:07 -07:00
|
|
|
swipeDirection |= SingleAxisSwipeDetector.DIRECTION_POSITIVE;
|
2018-04-24 13:42:59 -07:00
|
|
|
}
|
|
|
|
|
if (getTargetState(fromState, false /* isDragTowardPositive */) != fromState) {
|
2019-08-15 17:24:07 -07:00
|
|
|
swipeDirection |= SingleAxisSwipeDetector.DIRECTION_NEGATIVE;
|
2018-04-24 13:42:59 -07:00
|
|
|
}
|
|
|
|
|
return swipeDirection;
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-27 11:05:26 -07:00
|
|
|
@Override
|
2018-03-14 17:51:49 -07:00
|
|
|
public final boolean onControllerTouchEvent(MotionEvent ev) {
|
2017-10-27 11:05:26 -07:00
|
|
|
return mDetector.onTouchEvent(ev);
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-14 17:51:49 -07:00
|
|
|
protected float getShiftRange() {
|
|
|
|
|
return mLauncher.getAllAppsController().getShiftRange();
|
|
|
|
|
}
|
|
|
|
|
|
2018-04-06 14:22:46 -07:00
|
|
|
/**
|
|
|
|
|
* Returns the state to go to from fromState given the drag direction. If there is no state in
|
|
|
|
|
* that direction, returns fromState.
|
|
|
|
|
*/
|
2018-03-28 11:21:49 -07:00
|
|
|
protected abstract LauncherState getTargetState(LauncherState fromState,
|
|
|
|
|
boolean isDragTowardPositive);
|
|
|
|
|
|
2021-03-23 17:22:28 -07:00
|
|
|
protected abstract float initCurrentAnimation();
|
2018-03-14 17:51:49 -07:00
|
|
|
|
2018-03-28 11:21:49 -07:00
|
|
|
private boolean reinitCurrentAnimation(boolean reachedToState, boolean isDragTowardPositive) {
|
|
|
|
|
LauncherState newFromState = mFromState == null ? mLauncher.getStateManager().getState()
|
|
|
|
|
: reachedToState ? mToState : mFromState;
|
|
|
|
|
LauncherState newToState = getTargetState(newFromState, isDragTowardPositive);
|
|
|
|
|
|
2021-02-09 17:59:48 -08:00
|
|
|
onReinitToState(newToState);
|
|
|
|
|
|
2018-03-28 11:21:49 -07:00
|
|
|
if (newFromState == mFromState && newToState == mToState || (newFromState == newToState)) {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mFromState = newFromState;
|
|
|
|
|
mToState = newToState;
|
|
|
|
|
|
|
|
|
|
mStartProgress = 0;
|
2018-04-27 12:33:24 -05:00
|
|
|
if (mCurrentAnimation != null) {
|
2020-10-21 15:42:05 -07:00
|
|
|
mCurrentAnimation.getTarget().removeListener(mClearStateOnCancelListener);
|
2018-04-27 12:33:24 -05:00
|
|
|
}
|
2021-03-23 17:22:28 -07:00
|
|
|
mProgressMultiplier = initCurrentAnimation();
|
2018-03-28 11:21:49 -07:00
|
|
|
mCurrentAnimation.dispatchOnStart();
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-09 17:59:48 -08:00
|
|
|
protected void onReinitToState(LauncherState newToState) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
protected void onReachedFinalState(LauncherState newToState) {
|
|
|
|
|
}
|
|
|
|
|
|
2017-10-27 11:05:26 -07:00
|
|
|
@Override
|
2019-12-19 11:50:55 -08:00
|
|
|
public void onDragStart(boolean start, float startDisplacement) {
|
2018-05-22 14:09:29 -07:00
|
|
|
mStartState = mLauncher.getStateManager().getState();
|
2019-07-30 15:08:50 -07:00
|
|
|
mIsLogContainerSet = false;
|
2020-05-18 08:58:05 -07:00
|
|
|
|
2017-10-27 11:05:26 -07:00
|
|
|
if (mCurrentAnimation == null) {
|
2018-05-22 14:09:29 -07:00
|
|
|
mFromState = mStartState;
|
|
|
|
|
mToState = null;
|
2018-06-12 13:15:48 -07:00
|
|
|
cancelAnimationControllers();
|
2018-03-28 11:21:49 -07:00
|
|
|
reinitCurrentAnimation(false, mDetector.wasInitialTouchPositive());
|
|
|
|
|
mDisplacementShift = 0;
|
2017-10-27 11:05:26 -07:00
|
|
|
} else {
|
|
|
|
|
mCurrentAnimation.pause();
|
|
|
|
|
mStartProgress = mCurrentAnimation.getProgressFraction();
|
|
|
|
|
}
|
2018-04-19 11:39:34 -07:00
|
|
|
mCanBlockFling = mFromState == NORMAL;
|
2018-05-09 16:00:14 -07:00
|
|
|
mFlingBlockCheck.unblockFling();
|
2017-10-27 11:05:26 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
2018-09-12 15:47:06 -07:00
|
|
|
public boolean onDrag(float displacement) {
|
2018-03-28 11:21:49 -07:00
|
|
|
float deltaProgress = mProgressMultiplier * (displacement - mDisplacementShift);
|
|
|
|
|
float progress = deltaProgress + mStartProgress;
|
|
|
|
|
updateProgress(progress);
|
2019-03-22 19:15:39 -05:00
|
|
|
boolean isDragTowardPositive = mSwipeDirection.isPositive(
|
|
|
|
|
displacement - mDisplacementShift);
|
2018-03-28 11:21:49 -07:00
|
|
|
if (progress <= 0) {
|
|
|
|
|
if (reinitCurrentAnimation(false, isDragTowardPositive)) {
|
|
|
|
|
mDisplacementShift = displacement;
|
2018-05-09 16:00:14 -07:00
|
|
|
if (mCanBlockFling) {
|
|
|
|
|
mFlingBlockCheck.blockFling();
|
|
|
|
|
}
|
2018-03-28 11:21:49 -07:00
|
|
|
}
|
|
|
|
|
} else if (progress >= 1) {
|
|
|
|
|
if (reinitCurrentAnimation(true, isDragTowardPositive)) {
|
|
|
|
|
mDisplacementShift = displacement;
|
2018-05-09 16:00:14 -07:00
|
|
|
if (mCanBlockFling) {
|
|
|
|
|
mFlingBlockCheck.blockFling();
|
|
|
|
|
}
|
2018-03-28 11:21:49 -07:00
|
|
|
}
|
2018-05-09 16:00:14 -07:00
|
|
|
} else {
|
|
|
|
|
mFlingBlockCheck.onEvent();
|
2018-03-28 11:21:49 -07:00
|
|
|
}
|
2018-04-19 11:39:34 -07:00
|
|
|
|
2017-10-27 11:05:26 -07:00
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2019-07-30 15:08:50 -07:00
|
|
|
@Override
|
|
|
|
|
public boolean onDrag(float displacement, MotionEvent ev) {
|
|
|
|
|
if (!mIsLogContainerSet) {
|
|
|
|
|
if (mStartState == ALL_APPS) {
|
2020-09-15 00:34:10 -07:00
|
|
|
mStartContainerType = LAUNCHER_STATE_ALLAPPS;
|
2019-07-30 15:08:50 -07:00
|
|
|
} else if (mStartState == NORMAL) {
|
2020-09-15 00:34:10 -07:00
|
|
|
mStartContainerType = LAUNCHER_STATE_HOME;
|
2019-07-30 15:08:50 -07:00
|
|
|
} else if (mStartState == OVERVIEW) {
|
2020-09-15 00:34:10 -07:00
|
|
|
mStartContainerType = LAUNCHER_STATE_OVERVIEW;
|
2019-07-30 15:08:50 -07:00
|
|
|
}
|
|
|
|
|
mIsLogContainerSet = true;
|
|
|
|
|
}
|
|
|
|
|
return onDrag(displacement);
|
|
|
|
|
}
|
|
|
|
|
|
2018-03-21 09:32:27 -07:00
|
|
|
protected void updateProgress(float fraction) {
|
2020-06-10 15:36:52 -05:00
|
|
|
if (mCurrentAnimation == null) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
2018-03-21 09:32:27 -07:00
|
|
|
mCurrentAnimation.setPlayFraction(fraction);
|
2018-05-09 10:13:01 -07:00
|
|
|
}
|
|
|
|
|
|
2020-03-13 13:01:33 -07:00
|
|
|
/**
|
|
|
|
|
* Returns animation config for state transition between provided states
|
|
|
|
|
*/
|
|
|
|
|
protected StateAnimationConfig getConfigForStates(
|
|
|
|
|
LauncherState fromState, LauncherState toState) {
|
|
|
|
|
return new StateAnimationConfig();
|
2018-06-19 17:23:11 -07:00
|
|
|
}
|
|
|
|
|
|
2017-10-27 11:05:26 -07:00
|
|
|
@Override
|
2019-08-15 17:24:07 -07:00
|
|
|
public void onDragEnd(float velocity) {
|
2020-11-23 16:09:07 -08:00
|
|
|
if (mCurrentAnimation == null) {
|
|
|
|
|
// Unlikely, but we may have been canceled just before onDragEnd(). We assume whoever
|
|
|
|
|
// canceled us will handle a new state transition to clean up.
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2019-08-15 17:24:07 -07:00
|
|
|
boolean fling = mDetector.isFling(velocity);
|
2017-10-27 11:05:26 -07:00
|
|
|
|
2018-05-09 16:00:14 -07:00
|
|
|
boolean blockedFling = fling && mFlingBlockCheck.isBlocked();
|
2018-04-19 11:39:34 -07:00
|
|
|
if (blockedFling) {
|
|
|
|
|
fling = false;
|
|
|
|
|
}
|
|
|
|
|
|
2018-05-23 13:20:10 -07:00
|
|
|
final LauncherState targetState;
|
|
|
|
|
final float progress = mCurrentAnimation.getProgressFraction();
|
2020-01-16 18:30:45 -08:00
|
|
|
final float progressVelocity = velocity * mProgressMultiplier;
|
2018-11-16 16:42:07 -06:00
|
|
|
final float interpolatedProgress = mCurrentAnimation.getInterpolatedProgress();
|
2017-10-27 11:05:26 -07:00
|
|
|
if (fling) {
|
2018-03-14 17:51:49 -07:00
|
|
|
targetState =
|
|
|
|
|
Float.compare(Math.signum(velocity), Math.signum(mProgressMultiplier)) == 0
|
|
|
|
|
? mToState : mFromState;
|
|
|
|
|
// snap to top or bottom using the release velocity
|
|
|
|
|
} else {
|
2020-10-21 15:42:05 -07:00
|
|
|
targetState =
|
|
|
|
|
(interpolatedProgress > SUCCESS_TRANSITION_PROGRESS) ? mToState : mFromState;
|
2018-03-14 17:51:49 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
final float endProgress;
|
|
|
|
|
final float startProgress;
|
|
|
|
|
final long duration;
|
2018-04-19 11:39:34 -07:00
|
|
|
// Increase the duration if we prevented the fling, as we are going against a high velocity.
|
2018-05-09 16:00:14 -07:00
|
|
|
final int durationMultiplier = blockedFling && targetState == mFromState
|
|
|
|
|
? LauncherAnimUtils.blockedFlingDurationFactor(velocity) : 1;
|
2018-03-14 17:51:49 -07:00
|
|
|
|
|
|
|
|
if (targetState == mToState) {
|
|
|
|
|
endProgress = 1;
|
|
|
|
|
if (progress >= 1) {
|
|
|
|
|
duration = 0;
|
|
|
|
|
startProgress = 1;
|
2017-10-27 11:05:26 -07:00
|
|
|
} else {
|
2019-07-23 11:26:38 -07:00
|
|
|
startProgress = Utilities.boundToRange(progress
|
2020-01-16 18:30:45 -08:00
|
|
|
+ progressVelocity * getSingleFrameMs(mLauncher), 0f, 1f);
|
2019-08-15 17:24:07 -07:00
|
|
|
duration = BaseSwipeDetector.calculateDuration(velocity,
|
2018-04-19 11:39:34 -07:00
|
|
|
endProgress - Math.max(progress, 0)) * durationMultiplier;
|
2017-10-27 11:05:26 -07:00
|
|
|
}
|
|
|
|
|
} else {
|
2018-05-04 13:17:46 -07:00
|
|
|
// Let the state manager know that the animation didn't go to the target state,
|
|
|
|
|
// but don't cancel ourselves (we already clean up when the animation completes).
|
2020-10-21 15:42:05 -07:00
|
|
|
mCurrentAnimation.getTarget().removeListener(mClearStateOnCancelListener);
|
|
|
|
|
mCurrentAnimation.dispatchOnCancel();
|
2018-05-04 13:17:46 -07:00
|
|
|
|
2018-03-14 17:51:49 -07:00
|
|
|
endProgress = 0;
|
|
|
|
|
if (progress <= 0) {
|
|
|
|
|
duration = 0;
|
|
|
|
|
startProgress = 0;
|
2017-10-27 11:05:26 -07:00
|
|
|
} else {
|
2019-07-23 11:26:38 -07:00
|
|
|
startProgress = Utilities.boundToRange(progress
|
2020-01-16 18:30:45 -08:00
|
|
|
+ progressVelocity * getSingleFrameMs(mLauncher), 0f, 1f);
|
2019-08-15 17:24:07 -07:00
|
|
|
duration = BaseSwipeDetector.calculateDuration(velocity,
|
2018-04-19 11:39:34 -07:00
|
|
|
Math.min(progress, 1) - endProgress) * durationMultiplier;
|
2017-10-27 11:05:26 -07:00
|
|
|
}
|
|
|
|
|
}
|
2021-04-02 14:30:10 -07:00
|
|
|
if (targetState != mStartState) {
|
|
|
|
|
logReachedState(targetState);
|
|
|
|
|
}
|
2020-09-15 00:34:10 -07:00
|
|
|
mCurrentAnimation.setEndAction(() -> onSwipeInteractionCompleted(targetState));
|
2017-10-27 11:05:26 -07:00
|
|
|
ValueAnimator anim = mCurrentAnimation.getAnimationPlayer();
|
2018-03-14 17:51:49 -07:00
|
|
|
anim.setFloatValues(startProgress, endProgress);
|
2021-03-23 17:22:28 -07:00
|
|
|
updateSwipeCompleteAnimation(anim, duration, targetState, velocity, fling);
|
2020-02-25 14:37:01 -08:00
|
|
|
mCurrentAnimation.dispatchOnStart();
|
2020-02-10 12:18:42 -08:00
|
|
|
if (fling && targetState == LauncherState.ALL_APPS && !UNSTABLE_SPRINGS.get()) {
|
2018-05-22 23:12:10 -07:00
|
|
|
mLauncher.getAppsView().addSpringFromFlingUpdateListener(anim, velocity);
|
|
|
|
|
}
|
2017-10-27 11:05:26 -07:00
|
|
|
anim.start();
|
2018-04-19 11:39:34 -07:00
|
|
|
}
|
|
|
|
|
|
2018-03-21 09:32:27 -07:00
|
|
|
protected void updateSwipeCompleteAnimation(ValueAnimator animator, long expectedDuration,
|
|
|
|
|
LauncherState targetState, float velocity, boolean isFling) {
|
|
|
|
|
animator.setDuration(expectedDuration)
|
|
|
|
|
.setInterpolator(scrollInterpolatorForVelocity(velocity));
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-15 00:34:10 -07:00
|
|
|
protected void onSwipeInteractionCompleted(LauncherState targetState) {
|
2021-02-09 17:59:48 -08:00
|
|
|
onReachedFinalState(mToState);
|
2020-01-09 15:19:02 -08:00
|
|
|
clearState();
|
2020-10-21 15:42:05 -07:00
|
|
|
boolean shouldGoToTargetState = mGoingBetweenStates || (mToState != targetState);
|
2018-04-02 15:22:06 -07:00
|
|
|
if (shouldGoToTargetState) {
|
2020-09-15 00:34:10 -07:00
|
|
|
goToTargetState(targetState);
|
2019-07-11 16:55:01 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2020-09-15 00:34:10 -07:00
|
|
|
protected void goToTargetState(LauncherState targetState) {
|
2019-11-04 16:23:51 -08:00
|
|
|
if (!mLauncher.isInState(targetState)) {
|
|
|
|
|
// If we're already in the target state, don't jump to it at the end of the animation in
|
|
|
|
|
// case the user started interacting with it before the animation finished.
|
|
|
|
|
mLauncher.getStateManager().goToState(targetState, false /* animated */);
|
|
|
|
|
}
|
2021-04-26 09:52:47 -07:00
|
|
|
mLauncher.getRootView().getSysUiScrim().createSysuiMultiplierAnim(
|
2021-02-02 16:45:07 -08:00
|
|
|
1f).setDuration(0).start();
|
2018-03-14 17:51:49 -07:00
|
|
|
}
|
|
|
|
|
|
2020-09-15 00:34:10 -07:00
|
|
|
private void logReachedState(LauncherState targetState) {
|
2018-04-24 13:42:59 -07:00
|
|
|
// Transition complete. log the action
|
2020-06-19 02:58:53 -07:00
|
|
|
mLauncher.getStatsLogManager().logger()
|
2020-09-15 00:34:10 -07:00
|
|
|
.withSrcState(mStartState.statsLogOrdinal)
|
|
|
|
|
.withDstState(targetState.statsLogOrdinal)
|
2020-06-19 02:58:53 -07:00
|
|
|
.withContainerInfo(LauncherAtom.ContainerInfo.newBuilder()
|
|
|
|
|
.setWorkspace(
|
|
|
|
|
LauncherAtom.WorkspaceContainer.newBuilder()
|
|
|
|
|
.setPageIndex(mLauncher.getWorkspace().getCurrentPage()))
|
|
|
|
|
.build())
|
2020-09-15 00:34:10 -07:00
|
|
|
.log(StatsLogManager.getLauncherAtomEvent(mStartState.statsLogOrdinal,
|
|
|
|
|
targetState.statsLogOrdinal, mToState.ordinal > mFromState.ordinal
|
2020-06-19 02:58:53 -07:00
|
|
|
? LAUNCHER_UNKNOWN_SWIPEUP
|
|
|
|
|
: LAUNCHER_UNKNOWN_SWIPEDOWN));
|
2018-04-24 13:42:59 -07:00
|
|
|
}
|
|
|
|
|
|
2018-03-14 17:51:49 -07:00
|
|
|
protected void clearState() {
|
2018-06-05 11:56:08 -07:00
|
|
|
cancelAnimationControllers();
|
2020-10-21 15:42:05 -07:00
|
|
|
mGoingBetweenStates = true;
|
2020-01-09 15:19:02 -08:00
|
|
|
mDetector.finishedScrolling();
|
|
|
|
|
mDetector.setDetectableScrollConditions(0, false);
|
2018-06-05 11:56:08 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void cancelAnimationControllers() {
|
2018-03-14 17:51:49 -07:00
|
|
|
mCurrentAnimation = null;
|
2018-05-09 10:13:01 -07:00
|
|
|
}
|
2017-10-27 11:05:26 -07:00
|
|
|
}
|