Improve quick switch from home by tracking both x and y motion
- Add NoButtonQuickSwitchTouchController which uses BothAxesSwipeDetector to track horizontal and vertical motion. - Initially, we only detect swipe left to right to quick switch (like before), but then we allow swipe up to either go to overview (if you hold) or back home (if you don't hold). - xDisplacement transitions non-overview components out (e.g. shelf and workspace), and translates overview in. - yDisplacement translates overview up and scales it down Bug: 126596417 Change-Id: Id679ad84c08246e205c667a78ed5df00d7276258
This commit is contained in:
parent
132b5a0bf8
commit
37a0970bf5
|
@ -24,4 +24,8 @@ public class ShelfPeekAnim {
|
|||
|
||||
public enum ShelfAnimState {
|
||||
}
|
||||
|
||||
public boolean isPeeking() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,8 +21,15 @@ import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
|||
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_SCALE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_TRANSLATE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
|
||||
import static com.android.launcher3.anim.Interpolators.AGGRESSIVE_EASE;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
|
||||
import static com.android.quickstep.TaskViewUtils.findTaskViewToLaunch;
|
||||
import static com.android.quickstep.TaskViewUtils.getRecentsWindowAnimator;
|
||||
|
||||
|
@ -40,6 +47,7 @@ import androidx.annotation.Nullable;
|
|||
import com.android.launcher3.LauncherState.ScaleAndTranslation;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.anim.SpringAnimationBuilder;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||
|
@ -56,6 +64,9 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
|
|||
public static final int INDEX_SHELF_ANIM = 0;
|
||||
public static final int INDEX_RECENTS_FADE_ANIM = 1;
|
||||
public static final int INDEX_RECENTS_TRANSLATE_X_ANIM = 2;
|
||||
public static final int INDEX_PAUSE_TO_OVERVIEW_ANIM = 3;
|
||||
|
||||
public static final long ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW = 300;
|
||||
|
||||
public LauncherAppTransitionManagerImpl(Context context) {
|
||||
super(context);
|
||||
|
@ -145,7 +156,7 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
|
|||
|
||||
@Override
|
||||
public int getStateElementAnimationsCount() {
|
||||
return 3;
|
||||
return 4;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -191,6 +202,20 @@ public final class LauncherAppTransitionManagerImpl extends QuickstepAppTransiti
|
|||
.setStiffness(250)
|
||||
.setValues(values)
|
||||
.build(mLauncher);
|
||||
case INDEX_PAUSE_TO_OVERVIEW_ANIM: {
|
||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
||||
builder.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
|
||||
builder.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_3);
|
||||
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
|
||||
builder.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
|
||||
builder.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
|
||||
}
|
||||
LauncherStateManager stateManager = mLauncher.getStateManager();
|
||||
return stateManager.createAtomicAnimation(
|
||||
stateManager.getCurrentStableState(), OVERVIEW, builder,
|
||||
ANIM_ALL, ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW);
|
||||
}
|
||||
|
||||
default:
|
||||
return super.createStateElementAnimation(index, values);
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ import com.android.launcher3.popup.SystemShortcut;
|
|||
import com.android.launcher3.uioverrides.touchcontrollers.FlingAndHoldTouchController;
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.LandscapeEdgeSwipeController;
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.NavBarToHomeTouchController;
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.NoButtonQuickSwitchTouchController;
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.OverviewToAllAppsTouchController;
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.PortraitStatesTouchController;
|
||||
import com.android.launcher3.uioverrides.touchcontrollers.QuickSwitchTouchController;
|
||||
|
@ -214,7 +215,7 @@ public class QuickstepLauncher extends BaseQuickstepLauncher {
|
|||
ArrayList<TouchController> list = new ArrayList<>();
|
||||
list.add(getDragController());
|
||||
if (mode == NO_BUTTON) {
|
||||
list.add(new QuickSwitchTouchController(this));
|
||||
list.add(new NoButtonQuickSwitchTouchController(this));
|
||||
list.add(new NavBarToHomeTouchController(this));
|
||||
list.add(new FlingAndHoldTouchController(this));
|
||||
} else {
|
||||
|
|
|
@ -22,6 +22,7 @@ import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
|||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_SCALE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_X;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_OVERVIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
|
||||
|
@ -205,6 +206,7 @@ public class OverviewState extends LauncherState {
|
|||
builder.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2);
|
||||
builder.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
|
||||
builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
|
||||
builder.setInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, OVERSHOOT_1_7);
|
||||
builder.setInterpolator(ANIM_OVERVIEW_FADE, OVERSHOOT_1_2);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,25 +16,20 @@
|
|||
|
||||
package com.android.launcher3.uioverrides.touchcontrollers;
|
||||
|
||||
import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_PAUSE_TO_OVERVIEW_ANIM;
|
||||
import static com.android.launcher3.LauncherState.ALL_APPS;
|
||||
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW_PEEK;
|
||||
import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
|
||||
import static com.android.launcher3.LauncherStateManager.ATOMIC_OVERVIEW_PEEK_COMPONENT;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_HEADER_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_SCALE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_HOTSEAT_TRANSLATE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_SCALE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_3;
|
||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
|
||||
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
|
||||
|
||||
|
@ -46,12 +41,13 @@ import android.view.View;
|
|||
import android.view.ViewConfiguration;
|
||||
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherAppTransitionManagerImpl;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.quickstep.util.MotionPauseDetector;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
|
@ -79,7 +75,7 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
|
|||
|
||||
@Override
|
||||
protected long getAtomicDuration() {
|
||||
return 300;
|
||||
return LauncherAppTransitionManagerImpl.ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -179,15 +175,8 @@ public class FlingAndHoldTouchController extends PortraitStatesTouchController {
|
|||
mPeekAnim.cancel();
|
||||
}
|
||||
|
||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
||||
builder.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
|
||||
builder.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_3);
|
||||
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
|
||||
builder.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
|
||||
builder.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
|
||||
}
|
||||
AnimatorSet overviewAnim = mLauncher.getStateManager().createAtomicAnimation(
|
||||
NORMAL, OVERVIEW, builder, ANIM_ALL, ATOMIC_DURATION);
|
||||
Animator overviewAnim = mLauncher.getAppTransitionManager().createStateElementAnimation(
|
||||
INDEX_PAUSE_TO_OVERVIEW_ANIM);
|
||||
overviewAnim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
|
|
|
@ -0,0 +1,459 @@
|
|||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package com.android.launcher3.uioverrides.touchcontrollers;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_PAUSE_TO_OVERVIEW_ANIM;
|
||||
import static com.android.launcher3.LauncherState.HOTSEAT_ICONS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.LauncherState.QUICK_SWITCH;
|
||||
import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
|
||||
import static com.android.launcher3.anim.AlphaUpdateListener.ALPHA_CUTOFF_THRESHOLD;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_ALL_APPS_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_VERTICAL_PROGRESS;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_FADE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.ANIM_WORKSPACE_TRANSLATE;
|
||||
import static com.android.launcher3.anim.AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_0_75;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL_5;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.anim.Interpolators.scrollInterpolatorForVelocity;
|
||||
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_RIGHT;
|
||||
import static com.android.launcher3.touch.BothAxesSwipeDetector.DIRECTION_UP;
|
||||
import static com.android.launcher3.util.DefaultDisplay.getSingleFrameMs;
|
||||
import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
|
||||
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.CANCEL;
|
||||
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.HIDE;
|
||||
import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK;
|
||||
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.graphics.PointF;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.LauncherStateManager.AnimationConfig;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
||||
import com.android.launcher3.graphics.OverviewScrim;
|
||||
import com.android.launcher3.touch.BaseSwipeDetector;
|
||||
import com.android.launcher3.touch.BothAxesSwipeDetector;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.util.TouchController;
|
||||
import com.android.launcher3.util.VibratorWrapper;
|
||||
import com.android.quickstep.SystemUiProxy;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.util.MotionPauseDetector;
|
||||
import com.android.quickstep.util.ShelfPeekAnim;
|
||||
import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
|
||||
import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
||||
import com.android.quickstep.views.LauncherRecentsView;
|
||||
|
||||
/**
|
||||
* Handles quick switching to a recent task from the home screen. To give as much flexibility to
|
||||
* the user as possible, also handles swipe up and hold to go to overview and swiping back home.
|
||||
*/
|
||||
public class NoButtonQuickSwitchTouchController implements TouchController,
|
||||
BothAxesSwipeDetector.Listener, MotionPauseDetector.OnMotionPauseListener {
|
||||
|
||||
/** The minimum progress of the scale/translationY animation until drag end. */
|
||||
private static final float Y_ANIM_MIN_PROGRESS = 0.15f;
|
||||
private static final Interpolator FADE_OUT_INTERPOLATOR = DEACCEL_5;
|
||||
private static final Interpolator TRANSLATE_OUT_INTERPOLATOR = ACCEL_0_75;
|
||||
private static final Interpolator SCALE_DOWN_INTERPOLATOR = DEACCEL;
|
||||
|
||||
private final BaseQuickstepLauncher mLauncher;
|
||||
private final BothAxesSwipeDetector mSwipeDetector;
|
||||
private final ShelfPeekAnim mShelfPeekAnim;
|
||||
private final float mXRange;
|
||||
private final float mYRange;
|
||||
private final MotionPauseDetector mMotionPauseDetector;
|
||||
private final float mMotionPauseMinDisplacement;
|
||||
|
||||
private boolean mNoIntercept;
|
||||
private LauncherState mStartState;
|
||||
|
||||
private boolean mIsHomeScreenVisible = true;
|
||||
|
||||
// As we drag, we control 3 animations: one to get non-overview components out of the way,
|
||||
// and the other two to set overview properties based on x and y progress.
|
||||
private AnimatorPlaybackController mNonOverviewAnim;
|
||||
private AnimatorPlaybackController mXOverviewAnim;
|
||||
private AnimatorPlaybackController mYOverviewAnim;
|
||||
|
||||
public NoButtonQuickSwitchTouchController(BaseQuickstepLauncher launcher) {
|
||||
mLauncher = launcher;
|
||||
mSwipeDetector = new BothAxesSwipeDetector(mLauncher, this);
|
||||
mShelfPeekAnim = mLauncher.getShelfPeekAnim();
|
||||
mXRange = mLauncher.getDeviceProfile().widthPx / 2f;
|
||||
mYRange = LayoutUtils.getShelfTrackingDistance(mLauncher, mLauncher.getDeviceProfile());
|
||||
mMotionPauseDetector = new MotionPauseDetector(mLauncher);
|
||||
mMotionPauseMinDisplacement = mLauncher.getResources().getDimension(
|
||||
R.dimen.motion_pause_detector_min_displacement_from_app);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onControllerInterceptTouchEvent(MotionEvent ev) {
|
||||
if (ev.getAction() == MotionEvent.ACTION_DOWN) {
|
||||
mNoIntercept = !canInterceptTouch(ev);
|
||||
if (mNoIntercept) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Only detect horizontal swipe for intercept, then we will allow swipe up as well.
|
||||
mSwipeDetector.setDetectableScrollConditions(DIRECTION_RIGHT,
|
||||
false /* ignoreSlopWhenSettling */);
|
||||
}
|
||||
|
||||
if (mNoIntercept) {
|
||||
return false;
|
||||
}
|
||||
|
||||
onControllerTouchEvent(ev);
|
||||
return mSwipeDetector.isDraggingOrSettling();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onControllerTouchEvent(MotionEvent ev) {
|
||||
return mSwipeDetector.onTouchEvent(ev);
|
||||
}
|
||||
|
||||
private boolean canInterceptTouch(MotionEvent ev) {
|
||||
if (!mLauncher.isInState(LauncherState.NORMAL)) {
|
||||
return false;
|
||||
}
|
||||
if ((ev.getEdgeFlags() & Utilities.EDGE_NAV_BAR) == 0) {
|
||||
return false;
|
||||
}
|
||||
int stateFlags = SystemUiProxy.INSTANCE.get(mLauncher).getLastSystemUiStateFlags();
|
||||
if ((stateFlags & SYSUI_STATE_OVERVIEW_DISABLED) != 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDragStart(boolean start) {
|
||||
mMotionPauseDetector.clear();
|
||||
if (start) {
|
||||
mStartState = mLauncher.getStateManager().getState();
|
||||
|
||||
mMotionPauseDetector.setOnMotionPauseListener(this);
|
||||
|
||||
// We have detected horizontal drag start, now allow swipe up as well.
|
||||
mSwipeDetector.setDetectableScrollConditions(DIRECTION_RIGHT | DIRECTION_UP,
|
||||
false /* ignoreSlopWhenSettling */);
|
||||
|
||||
setupAnimators();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMotionPauseChanged(boolean isPaused) {
|
||||
ShelfAnimState shelfState = isPaused ? PEEK : HIDE;
|
||||
if (shelfState == PEEK) {
|
||||
// Some shelf elements (e.g. qsb) were hidden, but we need them visible when peeking.
|
||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
||||
AllAppsTransitionController allAppsController = mLauncher.getAllAppsController();
|
||||
allAppsController.setAlphas(NORMAL.getVisibleElements(mLauncher),
|
||||
new AnimationConfig(), builder);
|
||||
builder.build().setDuration(0).start();
|
||||
|
||||
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
|
||||
// Hotseat was hidden, but we need it visible when peeking.
|
||||
mLauncher.getHotseat().setAlpha(1);
|
||||
}
|
||||
}
|
||||
mShelfPeekAnim.setShelfState(shelfState, ShelfPeekAnim.INTERPOLATOR,
|
||||
ShelfPeekAnim.DURATION);
|
||||
VibratorWrapper.INSTANCE.get(mLauncher).vibrate(OVERVIEW_HAPTIC);
|
||||
}
|
||||
|
||||
private void setupAnimators() {
|
||||
// Animate the non-overview components (e.g. workspace, shelf) out of the way.
|
||||
AnimatorSetBuilder nonOverviewBuilder = new AnimatorSetBuilder();
|
||||
nonOverviewBuilder.setInterpolator(ANIM_WORKSPACE_FADE, FADE_OUT_INTERPOLATOR);
|
||||
nonOverviewBuilder.setInterpolator(ANIM_ALL_APPS_FADE, FADE_OUT_INTERPOLATOR);
|
||||
nonOverviewBuilder.setInterpolator(ANIM_WORKSPACE_TRANSLATE, TRANSLATE_OUT_INTERPOLATOR);
|
||||
nonOverviewBuilder.setInterpolator(ANIM_VERTICAL_PROGRESS, TRANSLATE_OUT_INTERPOLATOR);
|
||||
updateNonOverviewAnim(QUICK_SWITCH, nonOverviewBuilder, ANIM_ALL);
|
||||
mNonOverviewAnim.dispatchOnStart();
|
||||
|
||||
setupOverviewAnimators();
|
||||
}
|
||||
|
||||
/** Create state animation to control non-overview components. */
|
||||
private void updateNonOverviewAnim(LauncherState toState, AnimatorSetBuilder builder,
|
||||
@LauncherStateManager.AnimationComponents int animComponents) {
|
||||
builder.addFlag(FLAG_DONT_ANIMATE_OVERVIEW);
|
||||
long accuracy = (long) (Math.max(mXRange, mYRange) * 2);
|
||||
mNonOverviewAnim = mLauncher.getStateManager().createAnimationToNewWorkspace(toState,
|
||||
builder, accuracy, this::clearState, animComponents);
|
||||
}
|
||||
|
||||
private void setupOverviewAnimators() {
|
||||
final LauncherState fromState = QUICK_SWITCH;
|
||||
final LauncherState toState = OVERVIEW;
|
||||
LauncherState.ScaleAndTranslation fromScaleAndTranslation = fromState
|
||||
.getOverviewScaleAndTranslation(mLauncher);
|
||||
LauncherState.ScaleAndTranslation toScaleAndTranslation = toState
|
||||
.getOverviewScaleAndTranslation(mLauncher);
|
||||
// Update RecentView's translationX to have it start offscreen.
|
||||
LauncherRecentsView recentsView = mLauncher.getOverviewPanel();
|
||||
float startScale = Utilities.mapRange(
|
||||
SCALE_DOWN_INTERPOLATOR.getInterpolation(Y_ANIM_MIN_PROGRESS),
|
||||
fromScaleAndTranslation.scale,
|
||||
toScaleAndTranslation.scale);
|
||||
fromScaleAndTranslation.translationX = recentsView.getOffscreenTranslationX(startScale);
|
||||
|
||||
// Set RecentView's initial properties.
|
||||
recentsView.setScaleX(fromScaleAndTranslation.scale);
|
||||
recentsView.setScaleY(fromScaleAndTranslation.scale);
|
||||
recentsView.setTranslationX(fromScaleAndTranslation.translationX);
|
||||
recentsView.setTranslationY(fromScaleAndTranslation.translationY);
|
||||
recentsView.setContentAlpha(1);
|
||||
|
||||
// As we drag right, animate the following properties:
|
||||
// - RecentsView translationX
|
||||
// - OverviewScrim
|
||||
AnimatorSet xOverviewAnim = new AnimatorSet();
|
||||
xOverviewAnim.play(ObjectAnimator.ofFloat(recentsView, View.TRANSLATION_X,
|
||||
toScaleAndTranslation.translationX));
|
||||
xOverviewAnim.play(ObjectAnimator.ofFloat(
|
||||
mLauncher.getDragLayer().getOverviewScrim(), OverviewScrim.SCRIM_PROGRESS,
|
||||
toState.getOverviewScrimAlpha(mLauncher)));
|
||||
long xAccuracy = (long) (mXRange * 2);
|
||||
xOverviewAnim.setDuration(xAccuracy);
|
||||
mXOverviewAnim = AnimatorPlaybackController.wrap(xOverviewAnim, xAccuracy);
|
||||
mXOverviewAnim.dispatchOnStart();
|
||||
|
||||
// As we drag up, animate the following properties:
|
||||
// - RecentsView translationY
|
||||
// - RecentsView scale
|
||||
// - RecentsView fullscreenProgress
|
||||
AnimatorSet yAnimation = new AnimatorSet();
|
||||
Animator translateYAnim = ObjectAnimator.ofFloat(recentsView, View.TRANSLATION_Y,
|
||||
toScaleAndTranslation.translationY);
|
||||
Animator scaleAnim = ObjectAnimator.ofFloat(recentsView, SCALE_PROPERTY,
|
||||
toScaleAndTranslation.scale);
|
||||
Animator fullscreenProgressAnim = ObjectAnimator.ofFloat(recentsView, FULLSCREEN_PROGRESS,
|
||||
fromState.getOverviewFullscreenProgress(), toState.getOverviewFullscreenProgress());
|
||||
scaleAnim.setInterpolator(SCALE_DOWN_INTERPOLATOR);
|
||||
fullscreenProgressAnim.setInterpolator(SCALE_DOWN_INTERPOLATOR);
|
||||
yAnimation.play(translateYAnim);
|
||||
yAnimation.play(scaleAnim);
|
||||
yAnimation.play(fullscreenProgressAnim);
|
||||
long yAccuracy = (long) (mYRange * 2);
|
||||
yAnimation.setDuration(yAccuracy);
|
||||
mYOverviewAnim = AnimatorPlaybackController.wrap(yAnimation, yAccuracy);
|
||||
mYOverviewAnim.dispatchOnStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onDrag(PointF displacement, MotionEvent ev) {
|
||||
float xProgress = Math.max(0, displacement.x) / mXRange;
|
||||
float yProgress = Math.max(0, -displacement.y) / mYRange;
|
||||
yProgress = Utilities.mapRange(yProgress, Y_ANIM_MIN_PROGRESS, 1f);
|
||||
|
||||
boolean wasHomeScreenVisible = mIsHomeScreenVisible;
|
||||
if (wasHomeScreenVisible && mNonOverviewAnim != null) {
|
||||
mNonOverviewAnim.setPlayFraction(xProgress);
|
||||
}
|
||||
mIsHomeScreenVisible = FADE_OUT_INTERPOLATOR.getInterpolation(xProgress)
|
||||
<= 1 - ALPHA_CUTOFF_THRESHOLD;
|
||||
|
||||
if (wasHomeScreenVisible && !mIsHomeScreenVisible) {
|
||||
// Get the shelf all the way offscreen so it pops up when we decide to peek it.
|
||||
mShelfPeekAnim.setShelfState(HIDE, LINEAR, 0);
|
||||
}
|
||||
|
||||
// Only allow motion pause if the home screen is invisible, since some
|
||||
// home screen elements will appear in the shelf on motion pause.
|
||||
mMotionPauseDetector.setDisallowPause(mIsHomeScreenVisible
|
||||
|| -displacement.y < mMotionPauseMinDisplacement);
|
||||
mMotionPauseDetector.addPosition(displacement.y, ev.getEventTime());
|
||||
|
||||
if (mIsHomeScreenVisible) {
|
||||
// Cancel the shelf anim so it doesn't clobber mNonOverviewAnim.
|
||||
mShelfPeekAnim.setShelfState(CANCEL, LINEAR, 0);
|
||||
}
|
||||
|
||||
if (mXOverviewAnim != null) {
|
||||
mXOverviewAnim.setPlayFraction(xProgress);
|
||||
}
|
||||
if (mYOverviewAnim != null) {
|
||||
mYOverviewAnim.setPlayFraction(yProgress);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDragEnd(PointF velocity) {
|
||||
boolean horizontalFling = mSwipeDetector.isFling(velocity.x);
|
||||
boolean verticalFling = mSwipeDetector.isFling(velocity.y);
|
||||
boolean noFling = !horizontalFling && !verticalFling;
|
||||
int logAction = noFling ? Touch.SWIPE : Touch.FLING;
|
||||
if (mMotionPauseDetector.isPaused() && noFling) {
|
||||
cancelAnimations();
|
||||
|
||||
Animator overviewAnim = mLauncher.getAppTransitionManager().createStateElementAnimation(
|
||||
INDEX_PAUSE_TO_OVERVIEW_ANIM);
|
||||
overviewAnim.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
onAnimationToStateCompleted(OVERVIEW, logAction);
|
||||
}
|
||||
});
|
||||
overviewAnim.start();
|
||||
return;
|
||||
}
|
||||
|
||||
final LauncherState targetState;
|
||||
if (horizontalFling && verticalFling) {
|
||||
// Flinging left and up, left and down, or right and up all go back home.
|
||||
// Only flinging right and down goes to quick switch.
|
||||
targetState = velocity.x < 0 || velocity.y < 0 ? NORMAL : QUICK_SWITCH;
|
||||
} else if (horizontalFling) {
|
||||
targetState = velocity.x > 0 ? QUICK_SWITCH : NORMAL;
|
||||
} else if (verticalFling) {
|
||||
targetState = velocity.y > 0 ? QUICK_SWITCH : NORMAL;
|
||||
} else {
|
||||
// If user isn't flinging, just snap to the closest state based on x progress.
|
||||
boolean passedHorizontalThreshold = mXOverviewAnim.getInterpolatedProgress() > 0.5f;
|
||||
targetState = passedHorizontalThreshold ? QUICK_SWITCH : NORMAL;
|
||||
}
|
||||
|
||||
// Animate the various components to the target state.
|
||||
|
||||
float xProgress = mXOverviewAnim.getProgressFraction();
|
||||
float startXProgress = Utilities.boundToRange(xProgress
|
||||
+ velocity.x * getSingleFrameMs(mLauncher) / mXRange, 0f, 1f);
|
||||
final float endXProgress = targetState == NORMAL ? 0 : 1;
|
||||
long xDuration = BaseSwipeDetector.calculateDuration(velocity.x,
|
||||
Math.abs(endXProgress - startXProgress));
|
||||
ValueAnimator xOverviewAnim = mXOverviewAnim.getAnimationPlayer();
|
||||
xOverviewAnim.setFloatValues(startXProgress, endXProgress);
|
||||
xOverviewAnim.setDuration(xDuration)
|
||||
.setInterpolator(scrollInterpolatorForVelocity(velocity.x));
|
||||
mXOverviewAnim.dispatchOnStartWithVelocity(endXProgress, velocity.x);
|
||||
|
||||
boolean flingUpToNormal = verticalFling && velocity.y < 0 && targetState == NORMAL;
|
||||
|
||||
float yProgress = mYOverviewAnim.getProgressFraction();
|
||||
float startYProgress = Utilities.boundToRange(yProgress
|
||||
- velocity.y * getSingleFrameMs(mLauncher) / mYRange, 0f, 1f);
|
||||
final float endYProgress;
|
||||
if (flingUpToNormal) {
|
||||
endYProgress = 1;
|
||||
} else if (targetState == NORMAL) {
|
||||
// Keep overview at its current scale/translationY as it slides off the screen.
|
||||
endYProgress = startYProgress;
|
||||
} else {
|
||||
endYProgress = 0;
|
||||
}
|
||||
long yDuration = BaseSwipeDetector.calculateDuration(velocity.y,
|
||||
Math.abs(endYProgress - startYProgress));
|
||||
ValueAnimator yOverviewAnim = mYOverviewAnim.getAnimationPlayer();
|
||||
yOverviewAnim.setFloatValues(startYProgress, endYProgress);
|
||||
yOverviewAnim.setDuration(yDuration);
|
||||
mYOverviewAnim.dispatchOnStartWithVelocity(endYProgress, velocity.y);
|
||||
|
||||
ValueAnimator nonOverviewAnim = mNonOverviewAnim.getAnimationPlayer();
|
||||
if (flingUpToNormal && !mIsHomeScreenVisible) {
|
||||
// We are flinging to home while workspace is invisible, run the same staggered
|
||||
// animation as from an app.
|
||||
// Update mNonOverviewAnim to do nothing so it doesn't interfere.
|
||||
updateNonOverviewAnim(targetState, new AnimatorSetBuilder(), 0 /* animComponents */);
|
||||
nonOverviewAnim = mNonOverviewAnim.getAnimationPlayer();
|
||||
|
||||
new StaggeredWorkspaceAnim(mLauncher, null, velocity.y,
|
||||
false /* animateOverviewScrim */).start();
|
||||
} else {
|
||||
boolean canceled = targetState == NORMAL;
|
||||
if (canceled) {
|
||||
// Let the state manager know that the animation didn't go to the target state,
|
||||
// but don't clean up yet (we already clean up when the animation completes).
|
||||
mNonOverviewAnim.dispatchOnCancelWithoutCancelRunnable();
|
||||
}
|
||||
float startProgress = mNonOverviewAnim.getProgressFraction();
|
||||
float endProgress = canceled ? 0 : 1;
|
||||
nonOverviewAnim.setFloatValues(startProgress, endProgress);
|
||||
mNonOverviewAnim.dispatchOnStartWithVelocity(endProgress,
|
||||
horizontalFling ? velocity.x : velocity.y);
|
||||
}
|
||||
|
||||
nonOverviewAnim.setDuration(Math.max(xDuration, yDuration));
|
||||
mNonOverviewAnim.setEndAction(() -> onAnimationToStateCompleted(targetState, logAction));
|
||||
|
||||
cancelAnimations();
|
||||
xOverviewAnim.start();
|
||||
yOverviewAnim.start();
|
||||
nonOverviewAnim.start();
|
||||
}
|
||||
|
||||
private void onAnimationToStateCompleted(LauncherState targetState, int logAction) {
|
||||
mLauncher.getUserEventDispatcher().logStateChangeAction(logAction,
|
||||
getDirectionForLog(), mSwipeDetector.getDownX(), mSwipeDetector.getDownY(),
|
||||
LauncherLogProto.ContainerType.NAVBAR,
|
||||
mStartState.containerType,
|
||||
targetState.containerType,
|
||||
mLauncher.getWorkspace().getCurrentPage());
|
||||
mLauncher.getStateManager().goToState(targetState, false, this::clearState);
|
||||
}
|
||||
|
||||
private int getDirectionForLog() {
|
||||
return Utilities.isRtl(mLauncher.getResources()) ? Direction.LEFT : Direction.RIGHT;
|
||||
}
|
||||
|
||||
private void cancelAnimations() {
|
||||
if (mNonOverviewAnim != null) {
|
||||
mNonOverviewAnim.getAnimationPlayer().cancel();
|
||||
}
|
||||
if (mXOverviewAnim != null) {
|
||||
mXOverviewAnim.getAnimationPlayer().cancel();
|
||||
}
|
||||
if (mYOverviewAnim != null) {
|
||||
mYOverviewAnim.getAnimationPlayer().cancel();
|
||||
}
|
||||
mShelfPeekAnim.setShelfState(ShelfAnimState.CANCEL, LINEAR, 0);
|
||||
mMotionPauseDetector.clear();
|
||||
}
|
||||
|
||||
private void clearState() {
|
||||
cancelAnimations();
|
||||
mNonOverviewAnim = null;
|
||||
mXOverviewAnim = null;
|
||||
mYOverviewAnim = null;
|
||||
mIsHomeScreenVisible = true;
|
||||
mSwipeDetector.finishedScrolling();
|
||||
}
|
||||
}
|
|
@ -24,7 +24,6 @@ import static com.android.launcher3.LauncherAppTransitionManagerImpl.INDEX_SHELF
|
|||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.INSTANT;
|
||||
|
@ -52,10 +51,8 @@ import com.android.launcher3.DeviceProfile;
|
|||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherInitListener;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.allapps.DiscoveryBounce;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.AnimatorSetBuilder;
|
||||
import com.android.launcher3.appprediction.PredictionUiStateManager;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.launcher3.views.FloatingIconView;
|
||||
|
@ -194,18 +191,8 @@ public final class LauncherActivityInterface implements BaseActivityInterface<La
|
|||
|
||||
@Override
|
||||
public void playAtomicAnimation(float velocity) {
|
||||
// Setup workspace with 0 duration to prepare for our staggered animation.
|
||||
LauncherStateManager stateManager = launcher.getStateManager();
|
||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
||||
// setRecentsAttachedToAppWindow() will animate recents out.
|
||||
builder.addFlag(AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW);
|
||||
stateManager.createAtomicAnimation(BACKGROUND_APP, NORMAL, builder, ANIM_ALL, 0);
|
||||
builder.build().start();
|
||||
|
||||
// Stop scrolling so that it doesn't interfere with the translation offscreen.
|
||||
recentsView.getScroller().forceFinished(true);
|
||||
|
||||
new StaggeredWorkspaceAnim(launcher, workspaceView, velocity).start();
|
||||
new StaggeredWorkspaceAnim(launcher, workspaceView, velocity,
|
||||
true /* animateOverviewScrim */).start();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.android.quickstep.util;
|
|||
import static com.android.launcher3.LauncherAnimUtils.VIEW_TRANSLATE_Y;
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.LauncherStateManager.ANIM_ALL;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
|
||||
import android.animation.Animator;
|
||||
|
@ -33,6 +34,7 @@ import com.android.launcher3.CellLayout;
|
|||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherStateManager;
|
||||
import com.android.launcher3.LauncherStateManager.AnimationConfig;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.ShortcutAndWidgetContainer;
|
||||
|
@ -42,6 +44,7 @@ import com.android.launcher3.anim.PropertySetter;
|
|||
import com.android.launcher3.anim.SpringAnimationBuilder;
|
||||
import com.android.launcher3.graphics.OverviewScrim;
|
||||
import com.android.launcher3.views.IconLabelDotView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
/**
|
||||
* Creates an animation where all the workspace items are moved into their final location,
|
||||
|
@ -70,7 +73,9 @@ public class StaggeredWorkspaceAnim {
|
|||
* @param floatingViewOriginalView The FloatingIconView's original view.
|
||||
*/
|
||||
public StaggeredWorkspaceAnim(Launcher launcher, @Nullable View floatingViewOriginalView,
|
||||
float velocity) {
|
||||
float velocity, boolean animateOverviewScrim) {
|
||||
prepareToAnimate(launcher);
|
||||
|
||||
mVelocity = velocity;
|
||||
mOriginalView = floatingViewOriginalView;
|
||||
|
||||
|
@ -128,8 +133,10 @@ public class StaggeredWorkspaceAnim {
|
|||
addStaggeredAnimationForView(qsb, grid.inv.numRows + 2, totalRows);
|
||||
}
|
||||
|
||||
addScrimAnimationForState(launcher, BACKGROUND_APP, 0);
|
||||
addScrimAnimationForState(launcher, NORMAL, ALPHA_DURATION_MS);
|
||||
if (animateOverviewScrim) {
|
||||
addScrimAnimationForState(launcher, BACKGROUND_APP, 0);
|
||||
addScrimAnimationForState(launcher, NORMAL, ALPHA_DURATION_MS);
|
||||
}
|
||||
|
||||
mAnimators.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
|
@ -144,6 +151,21 @@ public class StaggeredWorkspaceAnim {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup workspace with 0 duration to prepare for our staggered animation.
|
||||
*/
|
||||
private void prepareToAnimate(Launcher launcher) {
|
||||
LauncherStateManager stateManager = launcher.getStateManager();
|
||||
AnimatorSetBuilder builder = new AnimatorSetBuilder();
|
||||
// setRecentsAttachedToAppWindow() will animate recents out.
|
||||
builder.addFlag(AnimatorSetBuilder.FLAG_DONT_ANIMATE_OVERVIEW);
|
||||
stateManager.createAtomicAnimation(BACKGROUND_APP, NORMAL, builder, ANIM_ALL, 0);
|
||||
builder.build().start();
|
||||
|
||||
// Stop scrolling so that it doesn't interfere with the translation offscreen.
|
||||
launcher.<RecentsView>getOverviewPanel().getScroller().forceFinished(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the animation.
|
||||
*/
|
||||
|
|
|
@ -18,6 +18,7 @@ package com.android.quickstep.views;
|
|||
import static com.android.launcher3.LauncherState.ALL_APPS_HEADER_EXTRA;
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.LauncherState.QUICK_SWITCH;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
|
@ -34,7 +35,9 @@ import android.graphics.Rect;
|
|||
import android.util.AttributeSet;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
|
@ -52,7 +55,8 @@ import com.android.quickstep.util.LayoutUtils;
|
|||
* From normal state to overview state, the shelf just fades in and does not move
|
||||
* From overview state to all-apps state the shelf moves up and fades in to cover the screen
|
||||
*/
|
||||
public class ShelfScrimView extends ScrimView implements NavigationModeChangeListener {
|
||||
public class ShelfScrimView extends ScrimView<BaseQuickstepLauncher>
|
||||
implements NavigationModeChangeListener {
|
||||
|
||||
// If the progress is more than this, shelf follows the finger, otherwise it moves faster to
|
||||
// cover the whole screen
|
||||
|
@ -193,8 +197,10 @@ public class ShelfScrimView extends ScrimView implements NavigationModeChangeLis
|
|||
if (mProgress >= 1) {
|
||||
mRemainingScreenColor = 0;
|
||||
mShelfColor = 0;
|
||||
LauncherState state = mLauncher.getStateManager().getState();
|
||||
if (mSysUINavigationMode == Mode.NO_BUTTON
|
||||
&& mLauncher.getStateManager().getState() == BACKGROUND_APP) {
|
||||
&& (state == BACKGROUND_APP || state == QUICK_SWITCH)
|
||||
&& mLauncher.getShelfPeekAnim().isPeeking()) {
|
||||
// Show the shelf background when peeking during swipe up.
|
||||
mShelfColor = setColorAlphaBound(mEndScrim, mMidAlpha);
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ import android.view.ViewGroup;
|
|||
*/
|
||||
public class AlphaUpdateListener extends AnimationSuccessListener
|
||||
implements AnimatorUpdateListener {
|
||||
private static final float ALPHA_CUTOFF_THRESHOLD = 0.01f;
|
||||
public static final float ALPHA_CUTOFF_THRESHOLD = 0.01f;
|
||||
|
||||
private View mView;
|
||||
|
||||
|
|
|
@ -26,15 +26,15 @@ import android.animation.TimeInterpolator;
|
|||
import android.animation.ValueAnimator;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.dynamicanimation.animation.DynamicAnimation;
|
||||
import androidx.dynamicanimation.animation.SpringAnimation;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import androidx.dynamicanimation.animation.DynamicAnimation;
|
||||
import androidx.dynamicanimation.animation.SpringAnimation;
|
||||
|
||||
/**
|
||||
* Helper class to control the playback of an {@link AnimatorSet}, with custom interpolators
|
||||
* and durations.
|
||||
|
@ -250,6 +250,17 @@ public abstract class AnimatorPlaybackController implements ValueAnimator.Animat
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets mOnCancelRunnable = null before dispatching the cancel and restoring the runnable. This
|
||||
* is intended to be used only if you need to cancel but want to defer cleaning up yourself.
|
||||
*/
|
||||
public void dispatchOnCancelWithoutCancelRunnable() {
|
||||
Runnable onCancel = mOnCancelRunnable;
|
||||
setOnCancelRunnable(null);
|
||||
dispatchOnCancel();
|
||||
setOnCancelRunnable(onCancel);
|
||||
}
|
||||
|
||||
public void dispatchOnCancel() {
|
||||
dispatchOnCancelRecursively(mAnim);
|
||||
}
|
||||
|
@ -283,10 +294,6 @@ public abstract class AnimatorPlaybackController implements ValueAnimator.Animat
|
|||
mOnCancelRunnable = runnable;
|
||||
}
|
||||
|
||||
public Runnable getOnCancelRunnable() {
|
||||
return mOnCancelRunnable;
|
||||
}
|
||||
|
||||
public void skipToEnd() {
|
||||
mSkipToEnd = true;
|
||||
for (SpringAnimation spring : mSprings) {
|
||||
|
|
|
@ -39,6 +39,7 @@ public class Interpolators {
|
|||
public static final Interpolator LINEAR = new LinearInterpolator();
|
||||
|
||||
public static final Interpolator ACCEL = new AccelerateInterpolator();
|
||||
public static final Interpolator ACCEL_0_75 = new AccelerateInterpolator(0.75f);
|
||||
public static final Interpolator ACCEL_1_5 = new AccelerateInterpolator(1.5f);
|
||||
public static final Interpolator ACCEL_2 = new AccelerateInterpolator(2);
|
||||
|
||||
|
@ -48,6 +49,7 @@ public class Interpolators {
|
|||
public static final Interpolator DEACCEL_2 = new DecelerateInterpolator(2);
|
||||
public static final Interpolator DEACCEL_2_5 = new DecelerateInterpolator(2.5f);
|
||||
public static final Interpolator DEACCEL_3 = new DecelerateInterpolator(3f);
|
||||
public static final Interpolator DEACCEL_5 = new DecelerateInterpolator(5f);
|
||||
|
||||
public static final Interpolator ACCEL_DEACCEL = new AccelerateDecelerateInterpolator();
|
||||
|
||||
|
|
|
@ -413,10 +413,7 @@ public abstract class AbstractStateChangeTouchController
|
|||
} else {
|
||||
// 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).
|
||||
Runnable onCancel = mCurrentAnimation.getOnCancelRunnable();
|
||||
mCurrentAnimation.setOnCancelRunnable(null);
|
||||
mCurrentAnimation.dispatchOnCancel();
|
||||
mCurrentAnimation.setOnCancelRunnable(onCancel);
|
||||
mCurrentAnimation.dispatchOnCancelWithoutCancelRunnable();
|
||||
|
||||
endProgress = 0;
|
||||
if (progress <= 0) {
|
||||
|
|
|
@ -77,7 +77,7 @@ import java.util.List;
|
|||
/**
|
||||
* Simple scrim which draws a flat color
|
||||
*/
|
||||
public class ScrimView extends View implements Insettable, OnChangeListener,
|
||||
public class ScrimView<T extends Launcher> extends View implements Insettable, OnChangeListener,
|
||||
AccessibilityStateChangeListener, StateListener {
|
||||
|
||||
public static final Property<ScrimView, Integer> DRAG_HANDLE_ALPHA =
|
||||
|
@ -101,7 +101,7 @@ public class ScrimView extends View implements Insettable, OnChangeListener,
|
|||
private final Rect mTempRect = new Rect();
|
||||
private final int[] mTempPos = new int[2];
|
||||
|
||||
protected final Launcher mLauncher;
|
||||
protected final T mLauncher;
|
||||
private final WallpaperColorInfo mWallpaperColorInfo;
|
||||
private final AccessibilityManager mAM;
|
||||
protected final int mEndScrim;
|
||||
|
@ -130,7 +130,7 @@ public class ScrimView extends View implements Insettable, OnChangeListener,
|
|||
|
||||
public ScrimView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mLauncher = Launcher.getLauncher(context);
|
||||
mLauncher = Launcher.cast(Launcher.getLauncher(context));
|
||||
mWallpaperColorInfo = WallpaperColorInfo.getInstance(context);
|
||||
mEndScrim = Themes.getAttrColor(context, R.attr.allAppsScrimColor);
|
||||
|
||||
|
|
Loading…
Reference in New Issue