Merge "Unifying swipe handling for fallback launcher" into ub-launcher3-rvc-dev am: 6928c3bc05
Change-Id: I1e6a90a23ce71bc398fc9195c137098f94e5f778
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
android:id="@+id/drag_layer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clipChildren="false"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<com.android.quickstep.fallback.FallbackRecentsView
|
||||
|
||||
+27
-42
@@ -49,64 +49,62 @@ import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_S
|
||||
import static com.android.launcher3.states.StateAnimationConfig.ANIM_WORKSPACE_TRANSLATE;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
||||
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.view.View;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import com.android.launcher3.CellLayout;
|
||||
import com.android.launcher3.Hotseat;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.LauncherState;
|
||||
import com.android.launcher3.LauncherState.ScaleAndTranslation;
|
||||
import com.android.launcher3.Workspace;
|
||||
import com.android.launcher3.allapps.AllAppsContainerView;
|
||||
import com.android.launcher3.allapps.AllAppsTransitionController;
|
||||
import com.android.launcher3.anim.SpringAnimationBuilder;
|
||||
import com.android.launcher3.statemanager.StateManager;
|
||||
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
|
||||
import com.android.launcher3.states.StateAnimationConfig;
|
||||
import com.android.launcher3.uioverrides.QuickstepLauncher;
|
||||
import com.android.quickstep.SysUINavigationMode;
|
||||
import com.android.quickstep.util.RecentsAtomicAnimationFactory;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
/**
|
||||
* Animation factory for quickstep specific transitions
|
||||
*/
|
||||
public class QuickstepAtomicAnimationFactory extends AtomicAnimationFactory<LauncherState> {
|
||||
public class QuickstepAtomicAnimationFactory extends
|
||||
RecentsAtomicAnimationFactory<Launcher, LauncherState> {
|
||||
|
||||
// Scale recents takes before animating in
|
||||
private static final float RECENTS_PREPARE_SCALE = 1.33f;
|
||||
|
||||
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;
|
||||
private static final int ANIM_COUNT = 4;
|
||||
public static final int INDEX_SHELF_ANIM = RecentsAtomicAnimationFactory.NEXT_INDEX + 0;
|
||||
public static final int INDEX_PAUSE_TO_OVERVIEW_ANIM =
|
||||
RecentsAtomicAnimationFactory.NEXT_INDEX + 1;
|
||||
|
||||
private static final int MY_ANIM_COUNT = 2;
|
||||
protected static final int NEXT_INDEX = RecentsAtomicAnimationFactory.NEXT_INDEX
|
||||
+ MY_ANIM_COUNT;
|
||||
|
||||
public static final long ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW = 300;
|
||||
|
||||
private final QuickstepLauncher mLauncher;
|
||||
|
||||
public QuickstepAtomicAnimationFactory(QuickstepLauncher launcher) {
|
||||
super(ANIM_COUNT);
|
||||
mLauncher = launcher;
|
||||
public QuickstepAtomicAnimationFactory(QuickstepLauncher activity) {
|
||||
super(activity, MY_ANIM_COUNT);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Animator createStateElementAnimation(int index, float... values) {
|
||||
switch (index) {
|
||||
case INDEX_SHELF_ANIM: {
|
||||
AllAppsTransitionController aatc = mLauncher.getAllAppsController();
|
||||
AllAppsTransitionController aatc = mActivity.getAllAppsController();
|
||||
Animator springAnim = aatc.createSpringAnimation(values);
|
||||
|
||||
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
|
||||
if ((OVERVIEW.getVisibleElements(mActivity) & HOTSEAT_ICONS) != 0) {
|
||||
// Translate hotseat with the shelf until reaching overview.
|
||||
float overviewProgress = OVERVIEW.getVerticalProgress(mLauncher);
|
||||
ScaleAndTranslation sat = OVERVIEW.getHotseatScaleAndTranslation(mLauncher);
|
||||
float overviewProgress = OVERVIEW.getVerticalProgress(mActivity);
|
||||
ScaleAndTranslation sat = OVERVIEW.getHotseatScaleAndTranslation(mActivity);
|
||||
float shiftRange = aatc.getShiftRange();
|
||||
if (values.length == 1) {
|
||||
values = new float[] {aatc.getProgress(), values[0]};
|
||||
@@ -114,9 +112,9 @@ public class QuickstepAtomicAnimationFactory extends AtomicAnimationFactory<Laun
|
||||
ValueAnimator hotseatAnim = ValueAnimator.ofFloat(values);
|
||||
hotseatAnim.addUpdateListener(anim -> {
|
||||
float progress = (Float) anim.getAnimatedValue();
|
||||
if (progress >= overviewProgress || mLauncher.isInState(BACKGROUND_APP)) {
|
||||
if (progress >= overviewProgress || mActivity.isInState(BACKGROUND_APP)) {
|
||||
float hotseatShift = (progress - overviewProgress) * shiftRange;
|
||||
mLauncher.getHotseat().setTranslationY(hotseatShift + sat.translationY);
|
||||
mActivity.getHotseat().setTranslationY(hotseatShift + sat.translationY);
|
||||
}
|
||||
});
|
||||
hotseatAnim.setInterpolator(LINEAR);
|
||||
@@ -130,34 +128,21 @@ public class QuickstepAtomicAnimationFactory extends AtomicAnimationFactory<Laun
|
||||
|
||||
return springAnim;
|
||||
}
|
||||
case INDEX_RECENTS_FADE_ANIM:
|
||||
return ObjectAnimator.ofFloat(mLauncher.getOverviewPanel(),
|
||||
RecentsView.CONTENT_ALPHA, values);
|
||||
case INDEX_RECENTS_TRANSLATE_X_ANIM: {
|
||||
RecentsView rv = mLauncher.getOverviewPanel();
|
||||
return new SpringAnimationBuilder(mLauncher)
|
||||
.setMinimumVisibleChange(1f / rv.getPageOffsetScale())
|
||||
.setDampingRatio(0.8f)
|
||||
.setStiffness(250)
|
||||
.setValues(values)
|
||||
.build(rv, ADJACENT_PAGE_OFFSET);
|
||||
}
|
||||
case INDEX_PAUSE_TO_OVERVIEW_ANIM: {
|
||||
StateAnimationConfig config = new StateAnimationConfig();
|
||||
config.duration = ATOMIC_DURATION_FROM_PAUSED_TO_OVERVIEW;
|
||||
|
||||
config.setInterpolator(ANIM_VERTICAL_PROGRESS, OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_ALL_APPS_FADE, DEACCEL_3);
|
||||
if ((OVERVIEW.getVisibleElements(mLauncher) & HOTSEAT_ICONS) != 0) {
|
||||
if ((OVERVIEW.getVisibleElements(mActivity) & HOTSEAT_ICONS) != 0) {
|
||||
config.setInterpolator(ANIM_HOTSEAT_SCALE, OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_HOTSEAT_TRANSLATE, OVERSHOOT_1_2);
|
||||
}
|
||||
|
||||
StateManager<LauncherState> stateManager = mLauncher.getStateManager();
|
||||
StateManager<LauncherState> stateManager = mActivity.getStateManager();
|
||||
return stateManager.createAtomicAnimation(
|
||||
stateManager.getCurrentStableState(), OVERVIEW, config);
|
||||
}
|
||||
|
||||
default:
|
||||
return super.createStateElementAnimation(index, values);
|
||||
}
|
||||
@@ -172,7 +157,7 @@ public class QuickstepAtomicAnimationFactory extends AtomicAnimationFactory<Laun
|
||||
config.setInterpolator(ANIM_OVERVIEW_SCALE, clampToProgress(ACCEL, 0, 0.9f));
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, ACCEL);
|
||||
config.setInterpolator(ANIM_OVERVIEW_FADE, DEACCEL_1_7);
|
||||
Workspace workspace = mLauncher.getWorkspace();
|
||||
Workspace workspace = mActivity.getWorkspace();
|
||||
|
||||
// Start from a higher workspace scale, but only if we're invisible so we don't jump.
|
||||
boolean isWorkspaceVisible = workspace.getVisibility() == VISIBLE;
|
||||
@@ -186,13 +171,13 @@ public class QuickstepAtomicAnimationFactory extends AtomicAnimationFactory<Laun
|
||||
workspace.setScaleX(0.92f);
|
||||
workspace.setScaleY(0.92f);
|
||||
}
|
||||
Hotseat hotseat = mLauncher.getHotseat();
|
||||
Hotseat hotseat = mActivity.getHotseat();
|
||||
boolean isHotseatVisible = hotseat.getVisibility() == VISIBLE && hotseat.getAlpha() > 0;
|
||||
if (!isHotseatVisible) {
|
||||
hotseat.setScaleX(0.92f);
|
||||
hotseat.setScaleY(0.92f);
|
||||
if (ENABLE_OVERVIEW_ACTIONS.get()) {
|
||||
AllAppsContainerView qsbContainer = mLauncher.getAppsView();
|
||||
AllAppsContainerView qsbContainer = mActivity.getAppsView();
|
||||
View qsb = qsbContainer.getSearchView();
|
||||
boolean qsbVisible = qsb.getVisibility() == VISIBLE && qsb.getAlpha() > 0;
|
||||
if (!qsbVisible) {
|
||||
@@ -209,7 +194,7 @@ public class QuickstepAtomicAnimationFactory extends AtomicAnimationFactory<Laun
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, OVERSHOOT_1_7);
|
||||
config.setInterpolator(ANIM_OVERVIEW_SCRIM_FADE, FAST_OUT_SLOW_IN);
|
||||
} else if ((fromState == NORMAL || fromState == HINT_STATE) && toState == OVERVIEW) {
|
||||
if (SysUINavigationMode.getMode(mLauncher) == NO_BUTTON) {
|
||||
if (SysUINavigationMode.getMode(mActivity) == NO_BUTTON) {
|
||||
config.setInterpolator(ANIM_WORKSPACE_SCALE,
|
||||
fromState == NORMAL ? ACCEL : OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_WORKSPACE_TRANSLATE, ACCEL);
|
||||
@@ -217,7 +202,7 @@ public class QuickstepAtomicAnimationFactory extends AtomicAnimationFactory<Laun
|
||||
config.setInterpolator(ANIM_WORKSPACE_SCALE, OVERSHOOT_1_2);
|
||||
|
||||
// Scale up the recents, if it is not coming from the side
|
||||
RecentsView overview = mLauncher.getOverviewPanel();
|
||||
RecentsView overview = mActivity.getOverviewPanel();
|
||||
if (overview.getVisibility() != VISIBLE || overview.getContentAlpha() == 0) {
|
||||
SCALE_PROPERTY.set(overview, RECENTS_PREPARE_SCALE);
|
||||
}
|
||||
@@ -225,7 +210,7 @@ public class QuickstepAtomicAnimationFactory extends AtomicAnimationFactory<Laun
|
||||
config.setInterpolator(ANIM_WORKSPACE_FADE, OVERSHOOT_1_2);
|
||||
config.setInterpolator(ANIM_OVERVIEW_SCALE, OVERSHOOT_1_2);
|
||||
Interpolator translationInterpolator = ENABLE_OVERVIEW_ACTIONS.get()
|
||||
&& removeShelfFromOverview(mLauncher)
|
||||
&& removeShelfFromOverview(mActivity)
|
||||
? OVERSHOOT_1_2
|
||||
: OVERSHOOT_1_7;
|
||||
config.setInterpolator(ANIM_OVERVIEW_TRANSLATE_X, translationInterpolator);
|
||||
|
||||
-1
@@ -77,7 +77,6 @@ final class AppToOverviewAnimationProvider<T extends StatefulActivity<?>> extend
|
||||
controller.dispatchOnStart();
|
||||
controller.getAnimationPlayer().end();
|
||||
});
|
||||
factory.onRemoteAnimationReceived(null);
|
||||
factory.createActivityInterface(RECENTS_LAUNCH_DURATION);
|
||||
factory.setRecentsAttachedToAppWindow(true, false);
|
||||
mActivity = activity;
|
||||
|
||||
@@ -55,7 +55,6 @@ import com.android.launcher3.views.FloatingIconView;
|
||||
import com.android.quickstep.RecentsAnimationCallbacks.RecentsAnimationListener;
|
||||
import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.AppWindowAnimationHelper;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.util.TaskViewSimulator;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
@@ -511,8 +510,8 @@ public abstract class BaseSwipeUpHandler<T extends StatefulActivity<?>, Q extend
|
||||
|
||||
public interface Factory {
|
||||
|
||||
BaseSwipeUpHandler newHandler(GestureState gestureState, long touchTimeMs,
|
||||
boolean continuingLastGesture, boolean isLikelyToStartNewTask);
|
||||
BaseSwipeUpHandler newHandler(
|
||||
GestureState gestureState, long touchTimeMs, boolean continuingLastGesture);
|
||||
}
|
||||
|
||||
protected interface RunningWindowAnim {
|
||||
|
||||
+27
-92
@@ -17,7 +17,6 @@ package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.BaseActivity.INVISIBLE_BY_STATE_HANDLER;
|
||||
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
import static com.android.launcher3.anim.Interpolators.DEACCEL;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.anim.Interpolators.OVERSHOOT_1_2;
|
||||
@@ -38,29 +37,24 @@ import static com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState.PEEK;
|
||||
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.animation.TimeInterpolator;
|
||||
import android.animation.ValueAnimator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.RectF;
|
||||
import android.os.Build;
|
||||
import android.os.SystemClock;
|
||||
import android.os.UserHandle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnApplyWindowInsetsListener;
|
||||
import android.view.ViewTreeObserver.OnDrawListener;
|
||||
import android.view.WindowInsets;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.UiThread;
|
||||
|
||||
import com.android.launcher3.AbstractFloatingView;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.Launcher;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.Utilities;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
@@ -72,7 +66,6 @@ import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Direction;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.Action.Touch;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto.ContainerType;
|
||||
import com.android.launcher3.util.TraceHelper;
|
||||
import com.android.launcher3.views.FloatingIconView;
|
||||
import com.android.quickstep.BaseActivityInterface.AnimationFactory;
|
||||
import com.android.quickstep.GestureState.GestureEndTarget;
|
||||
import com.android.quickstep.inputconsumers.OverviewInputConsumer;
|
||||
@@ -80,7 +73,6 @@ import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.quickstep.util.ShelfPeekAnim;
|
||||
import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
|
||||
import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
||||
import com.android.quickstep.util.TransformParams.TargetAlphaProvider;
|
||||
import com.android.quickstep.views.LiveTileOverlay;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
@@ -92,11 +84,12 @@ import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
|
||||
/**
|
||||
* Handles the navigation gestures when Launcher is the default home activity.
|
||||
* TODO: Merge this with BaseSwipeUpHandler
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.O)
|
||||
public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsView>
|
||||
implements OnApplyWindowInsetsListener {
|
||||
private static final String TAG = LauncherSwipeHandler.class.getSimpleName();
|
||||
public abstract class BaseSwipeUpHandlerV2<T extends StatefulActivity<?>, Q extends RecentsView>
|
||||
extends BaseSwipeUpHandler<T, Q> implements OnApplyWindowInsetsListener {
|
||||
private static final String TAG = BaseSwipeUpHandlerV2.class.getSimpleName();
|
||||
|
||||
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[16] : null;
|
||||
|
||||
@@ -108,9 +101,11 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
}
|
||||
|
||||
// Launcher UI related states
|
||||
private static final int STATE_LAUNCHER_PRESENT = getFlagForIndex(0, "STATE_LAUNCHER_PRESENT");
|
||||
private static final int STATE_LAUNCHER_STARTED = getFlagForIndex(1, "STATE_LAUNCHER_STARTED");
|
||||
private static final int STATE_LAUNCHER_DRAWN = getFlagForIndex(2, "STATE_LAUNCHER_DRAWN");
|
||||
protected static final int STATE_LAUNCHER_PRESENT =
|
||||
getFlagForIndex(0, "STATE_LAUNCHER_PRESENT");
|
||||
protected static final int STATE_LAUNCHER_STARTED =
|
||||
getFlagForIndex(1, "STATE_LAUNCHER_STARTED");
|
||||
protected static final int STATE_LAUNCHER_DRAWN = getFlagForIndex(2, "STATE_LAUNCHER_DRAWN");
|
||||
|
||||
// Internal initialization states
|
||||
private static final int STATE_APP_CONTROLLER_RECEIVED =
|
||||
@@ -122,7 +117,7 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
private static final int STATE_SCALED_CONTROLLER_RECENTS =
|
||||
getFlagForIndex(5, "STATE_SCALED_CONTROLLER_RECENTS");
|
||||
|
||||
private static final int STATE_HANDLER_INVALIDATED =
|
||||
protected static final int STATE_HANDLER_INVALIDATED =
|
||||
getFlagForIndex(6, "STATE_HANDLER_INVALIDATED");
|
||||
private static final int STATE_GESTURE_STARTED =
|
||||
getFlagForIndex(7, "STATE_GESTURE_STARTED");
|
||||
@@ -163,7 +158,7 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
*/
|
||||
private static final int LOG_NO_OP_PAGE_INDEX = -1;
|
||||
|
||||
private final TaskAnimationManager mTaskAnimationManager;
|
||||
protected final TaskAnimationManager mTaskAnimationManager;
|
||||
|
||||
// Either RectFSpringAnim (if animating home) or ObjectAnimator (from mCurrentShift) otherwise
|
||||
private RunningWindowAnim mRunningWindowAnim;
|
||||
@@ -193,7 +188,7 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
|
||||
private final Runnable mOnDeferredActivityLaunch = this::onDeferredActivityLaunch;
|
||||
|
||||
public LauncherSwipeHandler(Context context, RecentsAnimationDeviceState deviceState,
|
||||
public BaseSwipeUpHandlerV2(Context context, RecentsAnimationDeviceState deviceState,
|
||||
TaskAnimationManager taskAnimationManager, GestureState gestureState,
|
||||
long touchTimeMs, boolean continuingLastGesture,
|
||||
InputConsumerController inputConsumer) {
|
||||
@@ -222,9 +217,6 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
| STATE_GESTURE_CANCELLED,
|
||||
this::resetStateForAnimationCancel);
|
||||
|
||||
mStateCallback.runOnceAtState(STATE_LAUNCHER_STARTED | STATE_APP_CONTROLLER_RECEIVED,
|
||||
this::sendRemoteAnimationsToAnimationFactory);
|
||||
|
||||
mStateCallback.runOnceAtState(STATE_RESUME_LAST_TASK | STATE_APP_CONTROLLER_RECEIVED,
|
||||
this::resumeLastTask);
|
||||
mStateCallback.runOnceAtState(STATE_START_NEW_TASK | STATE_SCREENSHOT_CAPTURED,
|
||||
@@ -272,7 +264,7 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
@Override
|
||||
protected boolean onActivityInit(Boolean alreadyOnHome) {
|
||||
super.onActivityInit(alreadyOnHome);
|
||||
final Launcher activity = mActivityInterface.getCreatedActivity();
|
||||
final T activity = mActivityInterface.getCreatedActivity();
|
||||
if (mActivity == activity) {
|
||||
return true;
|
||||
}
|
||||
@@ -323,7 +315,7 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
}
|
||||
|
||||
private void onLauncherStart() {
|
||||
final Launcher activity = mActivityInterface.getCreatedActivity();
|
||||
final T activity = mActivityInterface.getCreatedActivity();
|
||||
if (mActivity != activity) {
|
||||
return;
|
||||
}
|
||||
@@ -411,6 +403,10 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
updateSysUiFlags(mCurrentShift.value);
|
||||
return;
|
||||
}
|
||||
notifyGestureAnimationStartToRecents();
|
||||
}
|
||||
|
||||
protected void notifyGestureAnimationStartToRecents() {
|
||||
mRecentsView.onGestureAnimationStart(mGestureState.getRunningTaskId());
|
||||
}
|
||||
|
||||
@@ -418,10 +414,6 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
mLauncherFrameDrawnTime = SystemClock.uptimeMillis();
|
||||
}
|
||||
|
||||
private void sendRemoteAnimationsToAnimationFactory() {
|
||||
mAnimationFactory.onRemoteAnimationReceived(mRecentsAnimationTargets);
|
||||
}
|
||||
|
||||
private void initializeLauncherAnimationController() {
|
||||
buildAnimationController();
|
||||
|
||||
@@ -633,7 +625,7 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
*/
|
||||
@UiThread
|
||||
private void notifyGestureStartedAsync() {
|
||||
final Launcher curActivity = mActivity;
|
||||
final T curActivity = mActivity;
|
||||
if (curActivity != null) {
|
||||
// Once the gesture starts, we can no longer transition home through the button, so
|
||||
// reset the force override of the activity visibility
|
||||
@@ -681,7 +673,7 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
endLauncherTransitionController();
|
||||
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
// Hide the task view, if not already hidden
|
||||
setTargetAlphaProvider(LauncherSwipeHandler::getHiddenTargetAlpha);
|
||||
setTargetAlphaProvider(BaseSwipeUpHandlerV2::getHiddenTargetAlpha);
|
||||
}
|
||||
|
||||
StatefulActivity activity = mActivityInterface.getCreatedActivity();
|
||||
@@ -911,6 +903,8 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
interpolator, target, velocityPxPerMs));
|
||||
}
|
||||
|
||||
protected abstract HomeAnimationFactory createHomeAnimationFactory(long duration);
|
||||
|
||||
@UiThread
|
||||
private void animateToProgressInternal(float start, float end, long duration,
|
||||
Interpolator interpolator, GestureEndTarget target, PointF velocityPxPerMs) {
|
||||
@@ -919,67 +913,7 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
maybeUpdateRecentsAttachedState();
|
||||
|
||||
if (mGestureState.getEndTarget() == HOME) {
|
||||
HomeAnimationFactory homeAnimFactory;
|
||||
if (mActivity != null) {
|
||||
final TaskView runningTaskView = mRecentsView.getRunningTaskView();
|
||||
final View workspaceView;
|
||||
if (runningTaskView != null
|
||||
&& runningTaskView.getTask().key.getComponent() != null) {
|
||||
workspaceView = mActivity.getWorkspace().getFirstMatchForAppClose(
|
||||
runningTaskView.getTask().key.getComponent().getPackageName(),
|
||||
UserHandle.of(runningTaskView.getTask().key.userId));
|
||||
} else {
|
||||
workspaceView = null;
|
||||
}
|
||||
final RectF iconLocation = new RectF();
|
||||
boolean canUseWorkspaceView =
|
||||
workspaceView != null && workspaceView.isAttachedToWindow();
|
||||
FloatingIconView floatingIconView = canUseWorkspaceView
|
||||
? FloatingIconView.getFloatingIconView(mActivity, workspaceView,
|
||||
true /* hideOriginal */, iconLocation, false /* isOpening */)
|
||||
: null;
|
||||
|
||||
mActivity.getRootView().setForceHideBackArrow(true);
|
||||
mActivityInterface.setHintUserWillBeActive();
|
||||
|
||||
homeAnimFactory = new HomeAnimationFactory(floatingIconView) {
|
||||
|
||||
@Override
|
||||
public RectF getWindowTargetRect() {
|
||||
if (canUseWorkspaceView) {
|
||||
return iconLocation;
|
||||
} else {
|
||||
return super.getWindowTargetRect();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
// Return an empty APC here since we have an non-user controlled animation
|
||||
// to home.
|
||||
long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx);
|
||||
return mActivity.getStateManager().createAnimationToNewWorkspace(
|
||||
NORMAL, accuracy, 0 /* animComponents */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playAtomicAnimation(float velocity) {
|
||||
new StaggeredWorkspaceAnim(mActivity, velocity,
|
||||
true /* animateOverviewScrim */).start();
|
||||
}
|
||||
};
|
||||
|
||||
} else {
|
||||
homeAnimFactory = new HomeAnimationFactory(null) {
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
return AnimatorPlaybackController.wrap(new AnimatorSet(), duration);
|
||||
}
|
||||
};
|
||||
mStateCallback.addChangeListener(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||
isPresent -> mRecentsView.startHome());
|
||||
}
|
||||
HomeAnimationFactory homeAnimFactory = createHomeAnimationFactory(duration);
|
||||
RectFSpringAnim windowAnim = createWindowAnimationToHome(start, homeAnimFactory);
|
||||
windowAnim.addAnimatorListener(new AnimationSuccessListener() {
|
||||
@Override
|
||||
@@ -1303,14 +1237,15 @@ public class LauncherSwipeHandler extends BaseSwipeUpHandler<Launcher, RecentsVi
|
||||
// If there are no targets or the animation not started, then there is nothing to finish
|
||||
mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED);
|
||||
} else {
|
||||
mRecentsAnimationController.finish(true /* toRecents */,
|
||||
() -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED),
|
||||
true /* sendUserLeaveHint */);
|
||||
finishRecentsControllerToHome(
|
||||
() -> mStateCallback.setStateOnUiThread(STATE_CURRENT_TASK_FINISHED));
|
||||
}
|
||||
ActiveGestureLog.INSTANCE.addLog("finishRecentsAnimation", true);
|
||||
doLogGesture(HOME);
|
||||
}
|
||||
|
||||
protected abstract void finishRecentsControllerToHome(Runnable callback);
|
||||
|
||||
private void setupLauncherUiAfterSwipeUpToRecentsAnimation() {
|
||||
endLauncherTransitionController();
|
||||
mActivityInterface.onSwipeUpToRecentsComplete();
|
||||
+23
-55
@@ -15,27 +15,21 @@
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.quickstep.SysUINavigationMode.Mode.NO_BUTTON;
|
||||
import static com.android.quickstep.fallback.RecentsState.BACKGROUND_APP;
|
||||
import static com.android.quickstep.fallback.RecentsState.DEFAULT;
|
||||
import static com.android.quickstep.views.RecentsView.CONTENT_ALPHA;
|
||||
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
|
||||
|
||||
import android.content.Context;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.touch.PagedOrientationHandler;
|
||||
import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||
import com.android.quickstep.fallback.RecentsState;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
@@ -55,9 +49,10 @@ public final class FallbackActivityInterface extends
|
||||
public static final FallbackActivityInterface INSTANCE = new FallbackActivityInterface();
|
||||
|
||||
private FallbackActivityInterface() {
|
||||
super(false);
|
||||
super(false, DEFAULT, BACKGROUND_APP);
|
||||
}
|
||||
|
||||
/** 2 */
|
||||
@Override
|
||||
public int getSwipeUpDestinationAndLength(DeviceProfile dp, Context context, Rect outRect,
|
||||
PagedOrientationHandler orientationHandler) {
|
||||
@@ -72,6 +67,13 @@ public final class FallbackActivityInterface extends
|
||||
}
|
||||
}
|
||||
|
||||
/** 4 */
|
||||
@Override
|
||||
public void onSwipeUpToHomeComplete() {
|
||||
onSwipeUpToRecentsComplete();
|
||||
}
|
||||
|
||||
/** 5 */
|
||||
@Override
|
||||
public void onAssistantVisibilityChanged(float visibility) {
|
||||
// This class becomes active when the screen is locked.
|
||||
@@ -79,51 +81,13 @@ public final class FallbackActivityInterface extends
|
||||
// set to zero prior to this class becoming active.
|
||||
}
|
||||
|
||||
/** 6 */
|
||||
@Override
|
||||
public AnimationFactory prepareRecentsUI(
|
||||
boolean activityVisible, Consumer<AnimatorPlaybackController> callback) {
|
||||
RecentsActivity activity = getCreatedActivity();
|
||||
if (activity == null) {
|
||||
return (transitionLength) -> { };
|
||||
}
|
||||
|
||||
activity.getStateManager().goToState(BACKGROUND_APP);
|
||||
FallbackRecentsView rv = activity.getOverviewPanel();
|
||||
rv.setContentAlpha(0);
|
||||
|
||||
return new AnimationFactory() {
|
||||
|
||||
boolean isAnimatingToRecents = false;
|
||||
|
||||
@Override
|
||||
public void onRemoteAnimationReceived(RemoteAnimationTargets targets) {
|
||||
isAnimatingToRecents = targets != null && targets.isAnimatingHome();
|
||||
if (!isAnimatingToRecents) {
|
||||
rv.setContentAlpha(1);
|
||||
}
|
||||
createActivityInterface(getSwipeUpDestinationAndLength(
|
||||
activity.getDeviceProfile(), activity, new Rect(),
|
||||
rv.getPagedOrientationHandler()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createActivityInterface(long transitionLength) {
|
||||
PendingAnimation pa = new PendingAnimation(transitionLength * 2);
|
||||
|
||||
if (isAnimatingToRecents) {
|
||||
pa.addFloat(rv, CONTENT_ALPHA, 0, 1, LINEAR);
|
||||
}
|
||||
|
||||
pa.addFloat(rv, SCALE_PROPERTY, rv.getMaxScaleForFullScreen(), 1, LINEAR);
|
||||
pa.addFloat(rv, FULLSCREEN_PROGRESS, 1, 0, LINEAR);
|
||||
AnimatorPlaybackController controller = pa.createPlaybackController();
|
||||
|
||||
// Since we are changing the start position of the UI, reapply the state, at the end
|
||||
controller.setEndAction(() -> activity.getStateManager().goToState(
|
||||
controller.getInterpolatedProgress() > 0.5 ? DEFAULT : BACKGROUND_APP));
|
||||
callback.accept(controller);
|
||||
}
|
||||
};
|
||||
DefaultAnimationFactory factory = new DefaultAnimationFactory(callback);
|
||||
factory.initUI();
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -166,6 +130,15 @@ public final class FallbackActivityInterface extends
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
|
||||
// In non-gesture mode, user might be clicking on the home button which would directly
|
||||
// start the home activity instead of going through recents. In that case, defer starting
|
||||
// recents until we are sure it is a gesture.
|
||||
return !deviceState.isFullyGesturalNavMode()
|
||||
|| super.deferStartingActivity(deviceState, ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContainerType() {
|
||||
RecentsActivity activity = getCreatedActivity();
|
||||
@@ -190,11 +163,6 @@ public final class FallbackActivityInterface extends
|
||||
activity.<RecentsView>getOverviewPanel().startHome();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getMultiWindowSize(Context context, DeviceProfile dp, PointF out) {
|
||||
out.set(dp.widthPx, dp.heightPx);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getExtraSpace(Context context, DeviceProfile dp,
|
||||
PagedOrientationHandler orientationHandler) {
|
||||
|
||||
+81
-501
@@ -15,537 +15,117 @@
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_1_5;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.HOME;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.LAST_TASK;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.NEW_TASK;
|
||||
import static com.android.quickstep.GestureState.GestureEndTarget.RECENTS;
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.RecentsActivity.EXTRA_TASK_ID;
|
||||
import static com.android.quickstep.RecentsActivity.EXTRA_THUMBNAIL;
|
||||
import static com.android.quickstep.views.RecentsView.UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.systemui.shared.system.RemoteAnimationTargetCompat.ACTIVITY_TYPE_HOME;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorSet;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.graphics.PointF;
|
||||
import android.os.Bundle;
|
||||
import android.util.ArrayMap;
|
||||
import android.view.MotionEvent;
|
||||
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.AnimationSuccessListener;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.util.ObjectWrapper;
|
||||
import com.android.quickstep.BaseActivityInterface.AnimationFactory;
|
||||
import com.android.quickstep.GestureState.GestureEndTarget;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||
import com.android.quickstep.util.RectFSpringAnim;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
import com.android.quickstep.util.TransformParams;
|
||||
import com.android.systemui.shared.system.ActivityManagerWrapper;
|
||||
import com.android.systemui.shared.system.ActivityOptionsCompat;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
import com.android.systemui.shared.system.SyncRtSurfaceTransactionApplierCompat.SurfaceParams.Builder;
|
||||
|
||||
/**
|
||||
* Handles the navigation gestures when a 3rd party launcher is the default home activity.
|
||||
*/
|
||||
public class FallbackSwipeHandler extends BaseSwipeUpHandler<RecentsActivity, FallbackRecentsView> {
|
||||
public class FallbackSwipeHandler extends
|
||||
BaseSwipeUpHandlerV2<RecentsActivity, FallbackRecentsView> {
|
||||
|
||||
private static final String[] STATE_NAMES = DEBUG_STATES ? new String[5] : null;
|
||||
|
||||
private static int getFlagForIndex(int index, String name) {
|
||||
if (DEBUG_STATES) {
|
||||
STATE_NAMES[index] = name;
|
||||
}
|
||||
return 1 << index;
|
||||
}
|
||||
|
||||
private static final int STATE_RECENTS_PRESENT =
|
||||
getFlagForIndex(0, "STATE_RECENTS_PRESENT");
|
||||
private static final int STATE_HANDLER_INVALIDATED =
|
||||
getFlagForIndex(1, "STATE_HANDLER_INVALIDATED");
|
||||
|
||||
private static final int STATE_GESTURE_CANCELLED =
|
||||
getFlagForIndex(2, "STATE_GESTURE_CANCELLED");
|
||||
private static final int STATE_GESTURE_COMPLETED =
|
||||
getFlagForIndex(3, "STATE_GESTURE_COMPLETED");
|
||||
private static final int STATE_APP_CONTROLLER_RECEIVED =
|
||||
getFlagForIndex(4, "STATE_APP_CONTROLLER_RECEIVED");
|
||||
|
||||
public static class EndTargetAnimationParams {
|
||||
private final float mEndProgress;
|
||||
private final long mDurationMultiplier;
|
||||
private final float mLauncherAlpha;
|
||||
|
||||
EndTargetAnimationParams(float endProgress, long durationMultiplier, float launcherAlpha) {
|
||||
mEndProgress = endProgress;
|
||||
mDurationMultiplier = durationMultiplier;
|
||||
mLauncherAlpha = launcherAlpha;
|
||||
}
|
||||
}
|
||||
private final ArrayMap<GestureEndTarget, EndTargetAnimationParams>
|
||||
mEndTargetAnimationParams = new ArrayMap();
|
||||
|
||||
private final AnimatedFloat mLauncherAlpha = new AnimatedFloat(this::onLauncherAlphaChanged);
|
||||
|
||||
private boolean mOverviewThresholdPassed = false;
|
||||
|
||||
private final boolean mInQuickSwitchMode;
|
||||
private final boolean mContinuingLastGesture;
|
||||
private FallbackHomeAnimationFactory mActiveAnimationFactory;
|
||||
private final boolean mRunningOverHome;
|
||||
private final boolean mSwipeUpOverHome;
|
||||
private boolean mTouchedHomeDuringTransition;
|
||||
|
||||
private final PointF mEndVelocityPxPerMs = new PointF(0, 0.5f);
|
||||
private RunningWindowAnim mFinishAnimation;
|
||||
|
||||
// Used to control Recents components throughout the swipe gesture.
|
||||
private AnimatorPlaybackController mLauncherTransitionController;
|
||||
private boolean mHasLauncherTransitionControllerStarted;
|
||||
|
||||
private AnimationFactory mAnimationFactory = (t) -> { };
|
||||
|
||||
public FallbackSwipeHandler(Context context, RecentsAnimationDeviceState deviceState,
|
||||
GestureState gestureState, InputConsumerController inputConsumer,
|
||||
boolean isLikelyToStartNewTask, boolean continuingLastGesture) {
|
||||
super(context, deviceState, gestureState, inputConsumer);
|
||||
TaskAnimationManager taskAnimationManager, GestureState gestureState, long touchTimeMs,
|
||||
boolean continuingLastGesture, InputConsumerController inputConsumer) {
|
||||
super(context, deviceState, taskAnimationManager, gestureState, touchTimeMs,
|
||||
continuingLastGesture, inputConsumer);
|
||||
|
||||
mInQuickSwitchMode = isLikelyToStartNewTask || continuingLastGesture;
|
||||
mContinuingLastGesture = continuingLastGesture;
|
||||
mRunningOverHome = ActivityManagerWrapper.isHomeTask(mGestureState.getRunningTask());
|
||||
mSwipeUpOverHome = mRunningOverHome && !mInQuickSwitchMode;
|
||||
|
||||
// Keep the home launcher invisible until we decide to land there.
|
||||
mLauncherAlpha.value = mRunningOverHome ? 1 : 0;
|
||||
if (mSwipeUpOverHome) {
|
||||
mTransformParams.setBaseAlphaCallback((t, a) -> 1 - mLauncherAlpha.value);
|
||||
} else {
|
||||
mTransformParams.setBaseAlphaCallback((t, a) -> mLauncherAlpha.value);
|
||||
}
|
||||
|
||||
// Going home has an extra long progress to ensure that it animates into the screen
|
||||
mEndTargetAnimationParams.put(HOME, new EndTargetAnimationParams(3, 100, 1));
|
||||
mEndTargetAnimationParams.put(RECENTS, new EndTargetAnimationParams(1, 300, 0));
|
||||
mEndTargetAnimationParams.put(LAST_TASK, new EndTargetAnimationParams(0, 150, 1));
|
||||
mEndTargetAnimationParams.put(NEW_TASK, new EndTargetAnimationParams(0, 150, 1));
|
||||
|
||||
initAfterSubclassConstructor();
|
||||
initStateCallbacks();
|
||||
}
|
||||
|
||||
private void initStateCallbacks() {
|
||||
mStateCallback = new MultiStateCallback(STATE_NAMES);
|
||||
|
||||
mStateCallback.runOnceAtState(STATE_HANDLER_INVALIDATED,
|
||||
this::onHandlerInvalidated);
|
||||
mStateCallback.runOnceAtState(STATE_RECENTS_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||
this::onHandlerInvalidatedWithRecents);
|
||||
|
||||
mStateCallback.runOnceAtState(STATE_GESTURE_CANCELLED | STATE_APP_CONTROLLER_RECEIVED,
|
||||
this::finishAnimationTargetSetAnimationComplete);
|
||||
|
||||
if (mInQuickSwitchMode) {
|
||||
mStateCallback.runOnceAtState(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED
|
||||
| STATE_RECENTS_PRESENT,
|
||||
this::finishAnimationTargetSet);
|
||||
} else {
|
||||
mStateCallback.runOnceAtState(STATE_GESTURE_COMPLETED | STATE_APP_CONTROLLER_RECEIVED,
|
||||
this::finishAnimationTargetSet);
|
||||
}
|
||||
}
|
||||
|
||||
private void onLauncherAlphaChanged() {
|
||||
if (mRecentsAnimationTargets != null && mGestureState.getEndTarget() == null) {
|
||||
applyWindowTransform();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean onActivityInit(Boolean alreadyOnHome) {
|
||||
super.onActivityInit(alreadyOnHome);
|
||||
mActivity = mActivityInterface.getCreatedActivity();
|
||||
mRecentsView = mActivity.getOverviewPanel();
|
||||
mRecentsView.setOnPageTransitionEndCallback(null);
|
||||
linkRecentsViewScroll();
|
||||
if (!mContinuingLastGesture) {
|
||||
if (mRunningOverHome) {
|
||||
mRecentsView.onGestureAnimationStart(mGestureState.getRunningTask());
|
||||
} else {
|
||||
mRecentsView.onGestureAnimationStart(mGestureState.getRunningTaskId());
|
||||
}
|
||||
}
|
||||
mStateCallback.setStateOnUiThread(STATE_RECENTS_PRESENT);
|
||||
mDeviceState.enableMultipleRegions(false);
|
||||
|
||||
mAnimationFactory = mActivityInterface.prepareRecentsUI(alreadyOnHome,
|
||||
this::onAnimatorPlaybackControllerCreated);
|
||||
mAnimationFactory.createActivityInterface(mTransitionDragLength);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initTransitionEndpoints(DeviceProfile dp) {
|
||||
super.initTransitionEndpoints(dp);
|
||||
if (canCreateNewOrUpdateExistingLauncherTransitionController()) {
|
||||
mAnimationFactory.createActivityInterface(mTransitionDragLength);
|
||||
}
|
||||
}
|
||||
|
||||
private void onAnimatorPlaybackControllerCreated(AnimatorPlaybackController anim) {
|
||||
mLauncherTransitionController = anim;
|
||||
mLauncherTransitionController.dispatchSetInterpolator(t -> t * mDragLengthFactor);
|
||||
mLauncherTransitionController.dispatchOnStart();
|
||||
updateLauncherTransitionProgress();
|
||||
}
|
||||
|
||||
private void updateLauncherTransitionProgress() {
|
||||
if (mLauncherTransitionController == null
|
||||
|| !canCreateNewOrUpdateExistingLauncherTransitionController()) {
|
||||
return;
|
||||
}
|
||||
// Normalize the progress to 0 to 1, as the animation controller will clamp it to that
|
||||
// anyway. The controller mimics the drag length factor by applying it to its interpolators.
|
||||
float progress = mCurrentShift.value / mDragLengthFactor;
|
||||
mLauncherTransitionController.setPlayFraction(progress);
|
||||
}
|
||||
|
||||
/**
|
||||
* We don't want to change mLauncherTransitionController if mGestureState.getEndTarget() == HOME
|
||||
* (it has its own animation) or if we're already animating the current controller.
|
||||
* @return Whether we can create the launcher controller or update its progress.
|
||||
*/
|
||||
private boolean canCreateNewOrUpdateExistingLauncherTransitionController() {
|
||||
return mGestureState.getEndTarget() != HOME && !mHasLauncherTransitionControllerStarted;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean moveWindowWithRecentsScroll() {
|
||||
return mInQuickSwitchMode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initWhenReady(Intent intent) {
|
||||
if (mInQuickSwitchMode) {
|
||||
// Only init if we are in quickswitch mode
|
||||
super.initWhenReady(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateDisplacement(float displacement) {
|
||||
if (!mInQuickSwitchMode) {
|
||||
super.updateDisplacement(displacement);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected InputConsumer createNewInputProxyHandler() {
|
||||
// Just consume all input on the active task
|
||||
return new InputConsumer() {
|
||||
@Override
|
||||
public int getType() {
|
||||
return InputConsumer.TYPE_NO_OP;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMotionEvent(MotionEvent ev) {
|
||||
mTouchedHomeDuringTransition = true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMotionPauseChanged(boolean isPaused) {
|
||||
if (!mInQuickSwitchMode && mDeviceState.isFullyGesturalNavMode()) {
|
||||
updateOverviewThresholdPassed(isPaused);
|
||||
}
|
||||
}
|
||||
|
||||
private void updateOverviewThresholdPassed(boolean passed) {
|
||||
if (passed != mOverviewThresholdPassed) {
|
||||
mOverviewThresholdPassed = passed;
|
||||
if (mSwipeUpOverHome) {
|
||||
mLauncherAlpha.animateToValue(mLauncherAlpha.value, passed ? 0 : 1)
|
||||
.setDuration(150).start();
|
||||
}
|
||||
performHapticFeedback();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Intent getLaunchIntent() {
|
||||
if (mInQuickSwitchMode || mSwipeUpOverHome || !mDeviceState.isFullyGesturalNavMode()) {
|
||||
return mGestureState.getOverviewIntent();
|
||||
} else {
|
||||
return mGestureState.getHomeIntent();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateFinalShift() {
|
||||
mTransformParams.setProgress(mCurrentShift.value);
|
||||
if (mRecentsAnimationController != null) {
|
||||
boolean swipeUpThresholdPassed = mCurrentShift.value > 1 - UPDATE_SYSUI_FLAGS_THRESHOLD;
|
||||
mRecentsAnimationController.setUseLauncherSystemBarFlags(mInQuickSwitchMode
|
||||
|| swipeUpThresholdPassed);
|
||||
mRecentsAnimationController.setSplitScreenMinimized(!mInQuickSwitchMode
|
||||
&& swipeUpThresholdPassed);
|
||||
}
|
||||
|
||||
if (!mInQuickSwitchMode && !mDeviceState.isFullyGesturalNavMode()) {
|
||||
updateOverviewThresholdPassed(mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW);
|
||||
}
|
||||
|
||||
applyWindowTransform();
|
||||
updateLauncherTransitionProgress();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGestureCancelled() {
|
||||
updateDisplacement(0);
|
||||
mGestureState.setEndTarget(LAST_TASK);
|
||||
mStateCallback.setStateOnUiThread(STATE_GESTURE_CANCELLED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGestureEnded(float endVelocity, PointF velocity, PointF downPos) {
|
||||
mEndVelocityPxPerMs.set(0, velocity.y / 1000);
|
||||
if (mInQuickSwitchMode) {
|
||||
// For now set it to non-null, it will be reset before starting the animation
|
||||
mGestureState.setEndTarget(LAST_TASK);
|
||||
} else {
|
||||
float flingThreshold = mContext.getResources()
|
||||
.getDimension(R.dimen.quickstep_fling_threshold_velocity);
|
||||
boolean isFling = Math.abs(endVelocity) > flingThreshold;
|
||||
|
||||
if (mDeviceState.isFullyGesturalNavMode()) {
|
||||
if (isFling) {
|
||||
mGestureState.setEndTarget(endVelocity < 0 ? HOME : LAST_TASK);
|
||||
} else if (mOverviewThresholdPassed) {
|
||||
mGestureState.setEndTarget(RECENTS);
|
||||
} else {
|
||||
mGestureState.setEndTarget(mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW
|
||||
? HOME
|
||||
: LAST_TASK);
|
||||
}
|
||||
} else {
|
||||
GestureEndTarget startState = mSwipeUpOverHome ? HOME : LAST_TASK;
|
||||
if (isFling) {
|
||||
mGestureState.setEndTarget(endVelocity < 0 ? RECENTS : startState);
|
||||
} else {
|
||||
mGestureState.setEndTarget(mCurrentShift.value >= MIN_PROGRESS_FOR_OVERVIEW
|
||||
? RECENTS
|
||||
: startState);
|
||||
}
|
||||
}
|
||||
}
|
||||
mStateCallback.setStateOnUiThread(STATE_GESTURE_COMPLETED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onConsumerAboutToBeSwitched() {
|
||||
if (mInQuickSwitchMode && mGestureState.getEndTarget() != null) {
|
||||
mGestureState.setEndTarget(NEW_TASK);
|
||||
|
||||
mCanceled = true;
|
||||
mCurrentShift.cancelAnimation();
|
||||
if (mFinishAnimation != null) {
|
||||
mFinishAnimation.cancel();
|
||||
}
|
||||
|
||||
if (mRecentsView != null) {
|
||||
mRecentsView.setOnScrollChangeListener(null);
|
||||
}
|
||||
} else {
|
||||
mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
}
|
||||
|
||||
private void onHandlerInvalidated() {
|
||||
mActivityInitListener.unregister();
|
||||
if (mGestureEndCallback != null) {
|
||||
mGestureEndCallback.run();
|
||||
}
|
||||
if (mFinishAnimation != null) {
|
||||
mFinishAnimation.end();
|
||||
}
|
||||
}
|
||||
|
||||
private void onHandlerInvalidatedWithRecents() {
|
||||
mRecentsView.onGestureAnimationEnd();
|
||||
mRecentsView.setDisallowScrollToClearAll(false);
|
||||
mRecentsView.getClearAllButton().setVisibilityAlpha(1);
|
||||
}
|
||||
|
||||
private void finishAnimationTargetSetAnimationComplete() {
|
||||
switch (mGestureState.getEndTarget()) {
|
||||
case HOME: {
|
||||
if (mSwipeUpOverHome) {
|
||||
mRecentsAnimationController.finish(false, null, false);
|
||||
// Send a home intent to clear the task stack
|
||||
mContext.startActivity(mGestureState.getHomeIntent());
|
||||
} else {
|
||||
// Notify swipe-to-home (recents animation) is finished
|
||||
SystemUiProxy.INSTANCE.get(mContext).notifySwipeToHomeFinished();
|
||||
mRecentsAnimationController.finish(true, () -> {
|
||||
if (!mTouchedHomeDuringTransition) {
|
||||
// If the user hasn't interacted with the screen during the transition,
|
||||
// send a home intent so launcher can go to the default home screen.
|
||||
// (If they are trying to touch something, we don't want to interfere.)
|
||||
mContext.startActivity(mGestureState.getHomeIntent());
|
||||
}
|
||||
}, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LAST_TASK:
|
||||
mRecentsAnimationController.finish(false, null, false);
|
||||
break;
|
||||
case RECENTS: {
|
||||
if (mSwipeUpOverHome || !mDeviceState.isFullyGesturalNavMode()) {
|
||||
mRecentsAnimationController.finish(true, null, true);
|
||||
break;
|
||||
}
|
||||
|
||||
final int runningTaskId = mGestureState.getRunningTaskId();
|
||||
ThumbnailData thumbnail = mRecentsAnimationController.screenshotTask(runningTaskId);
|
||||
mRecentsAnimationController.setDeferCancelUntilNextTransition(true /* defer */,
|
||||
false /* screenshot */);
|
||||
|
||||
ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
|
||||
ActivityOptionsCompat.setFreezeRecentTasksList(options);
|
||||
|
||||
Bundle extras = new Bundle();
|
||||
extras.putBinder(EXTRA_THUMBNAIL, new ObjectWrapper<>(thumbnail));
|
||||
extras.putInt(EXTRA_TASK_ID, runningTaskId);
|
||||
|
||||
Intent intent = new Intent(mGestureState.getOverviewIntent())
|
||||
.putExtras(extras);
|
||||
mContext.startActivity(intent, options.toBundle());
|
||||
mRecentsAnimationController.cleanupScreenshot();
|
||||
break;
|
||||
}
|
||||
case NEW_TASK: {
|
||||
startNewTask(success -> { });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
}
|
||||
|
||||
private void finishAnimationTargetSet() {
|
||||
if (mInQuickSwitchMode) {
|
||||
// Recalculate the end target, some views might have been initialized after
|
||||
// gesture has ended.
|
||||
if (mRecentsView == null || !hasTargets()) {
|
||||
mGestureState.setEndTarget(LAST_TASK);
|
||||
} else {
|
||||
final int runningTaskIndex = getLastAppearedTaskIndex();
|
||||
final int taskToLaunch = mRecentsView.getNextPage();
|
||||
mGestureState.setEndTarget(
|
||||
(runningTaskIndex >= 0 && taskToLaunch != runningTaskIndex)
|
||||
? NEW_TASK
|
||||
: LAST_TASK);
|
||||
}
|
||||
}
|
||||
|
||||
EndTargetAnimationParams params = mEndTargetAnimationParams.get(mGestureState.getEndTarget());
|
||||
float endProgress = params.mEndProgress;
|
||||
long duration = (long) (params.mDurationMultiplier *
|
||||
Math.abs(endProgress - mCurrentShift.value));
|
||||
if (mRecentsView != null) {
|
||||
duration = Math.max(duration, mRecentsView.getScroller().getDuration());
|
||||
}
|
||||
if (mCurrentShift.value != endProgress || mInQuickSwitchMode) {
|
||||
AnimationSuccessListener endListener = new AnimationSuccessListener() {
|
||||
|
||||
@Override
|
||||
public void onAnimationSuccess(Animator animator) {
|
||||
if (mRecentsView != null) {
|
||||
mRecentsView.setOnPageTransitionEndCallback(FallbackSwipeHandler.this
|
||||
::finishAnimationTargetSetAnimationComplete);
|
||||
} else {
|
||||
finishAnimationTargetSetAnimationComplete();
|
||||
}
|
||||
mFinishAnimation = null;
|
||||
}
|
||||
};
|
||||
|
||||
if (mGestureState.getEndTarget() == HOME && !mRunningOverHome) {
|
||||
mRecentsAnimationController.enableInputProxy(mInputConsumer,
|
||||
this::createNewInputProxyHandler);
|
||||
RectFSpringAnim anim = createWindowAnimationToHome(mCurrentShift.value, duration);
|
||||
anim.addAnimatorListener(endListener);
|
||||
anim.start(mContext, mEndVelocityPxPerMs);
|
||||
mFinishAnimation = RunningWindowAnim.wrap(anim);
|
||||
} else {
|
||||
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
anim.play(mLauncherAlpha.animateToValue(
|
||||
mLauncherAlpha.value, params.mLauncherAlpha));
|
||||
anim.play(mCurrentShift.animateToValue(mCurrentShift.value, endProgress));
|
||||
|
||||
anim.setDuration(duration);
|
||||
anim.addListener(endListener);
|
||||
anim.start();
|
||||
mFinishAnimation = RunningWindowAnim.wrap(anim);
|
||||
}
|
||||
|
||||
} else {
|
||||
finishAnimationTargetSetAnimationComplete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationStart(RecentsAnimationController controller,
|
||||
RecentsAnimationTargets targets) {
|
||||
super.onRecentsAnimationStart(controller, targets);
|
||||
mRecentsAnimationController.enableInputConsumer();
|
||||
applyWindowTransform();
|
||||
|
||||
mStateCallback.setStateOnUiThread(STATE_APP_CONTROLLER_RECEIVED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRecentsAnimationCanceled(ThumbnailData thumbnailData) {
|
||||
mStateCallback.setStateOnUiThread(STATE_HANDLER_INVALIDATED);
|
||||
|
||||
// Defer clearing the controller and the targets until after we've updated the state
|
||||
super.onRecentsAnimationCanceled(thumbnailData);
|
||||
protected HomeAnimationFactory createHomeAnimationFactory(long duration) {
|
||||
mActiveAnimationFactory = new FallbackHomeAnimationFactory(duration);
|
||||
ActivityOptions options = ActivityOptions.makeCustomAnimation(mContext, 0, 0);
|
||||
mContext.startActivity(new Intent(mGestureState.getHomeIntent()), options.toBundle());
|
||||
return mActiveAnimationFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean handleTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
|
||||
return true;
|
||||
}
|
||||
if (mActiveAnimationFactory != null
|
||||
&& mActiveAnimationFactory.handleHomeTaskAppeared(appearedTaskTarget)) {
|
||||
mActiveAnimationFactory = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an animation that transforms the current app window into the home app.
|
||||
* @param startProgress The progress of {@link #mCurrentShift} to start the window from.
|
||||
*/
|
||||
private RectFSpringAnim createWindowAnimationToHome(float startProgress, long duration) {
|
||||
HomeAnimationFactory factory = new HomeAnimationFactory(null) {
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
AnimatorSet anim = new AnimatorSet();
|
||||
Animator fadeInLauncher = mLauncherAlpha.animateToValue(mLauncherAlpha.value, 1);
|
||||
fadeInLauncher.setInterpolator(ACCEL_2);
|
||||
anim.play(fadeInLauncher);
|
||||
anim.setDuration(duration);
|
||||
return AnimatorPlaybackController.wrap(anim, duration);
|
||||
}
|
||||
};
|
||||
return createWindowAnimationToHome(startProgress, factory);
|
||||
return super.handleTaskAppeared(appearedTaskTarget);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getWindowAlpha(float progress) {
|
||||
return 1 - ACCEL_1_5.getInterpolation(progress);
|
||||
protected void finishRecentsControllerToHome(Runnable callback) {
|
||||
mRecentsAnimationController.finish(
|
||||
false /* toRecents */, callback, true /* sendUserLeaveHint */);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void notifyGestureAnimationStartToRecents() {
|
||||
if (mRunningOverHome) {
|
||||
mRecentsView.onGestureAnimationStartOnHome(mGestureState.getRunningTask());
|
||||
} else {
|
||||
super.notifyGestureAnimationStartToRecents();
|
||||
}
|
||||
}
|
||||
|
||||
private class FallbackHomeAnimationFactory extends HomeAnimationFactory
|
||||
implements TransformParams.BuilderProxy {
|
||||
|
||||
private final TransformParams mHomeAlphaParams = new TransformParams();
|
||||
private final AnimatedFloat mHomeAlpha = new AnimatedFloat(this::updateHomeAlpha);
|
||||
|
||||
private final long mDuration;
|
||||
FallbackHomeAnimationFactory(long duration) {
|
||||
super(null);
|
||||
mDuration = duration;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
PendingAnimation pa = new PendingAnimation(mDuration);
|
||||
pa.setFloat(mHomeAlpha, AnimatedFloat.VALUE, 1, LINEAR);
|
||||
return pa.createPlaybackController();
|
||||
}
|
||||
|
||||
private void updateHomeAlpha() {
|
||||
mHomeAlphaParams.setProgress(mHomeAlpha.value);
|
||||
if (mHomeAlphaParams.getTargetSet() != null) {
|
||||
mHomeAlphaParams.applySurfaceParams(mHomeAlphaParams.createSurfaceParams(this));
|
||||
}
|
||||
}
|
||||
|
||||
public boolean handleHomeTaskAppeared(RemoteAnimationTargetCompat appearedTaskTarget) {
|
||||
if (appearedTaskTarget.activityType == ACTIVITY_TYPE_HOME) {
|
||||
RemoteAnimationTargets targets = new RemoteAnimationTargets(
|
||||
new RemoteAnimationTargetCompat[] {appearedTaskTarget},
|
||||
new RemoteAnimationTargetCompat[0], appearedTaskTarget.mode);
|
||||
mHomeAlphaParams.setTargetSet(targets);
|
||||
updateHomeAlpha();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBuildParams(Builder builder, RemoteAnimationTargetCompat app, int targetMode,
|
||||
TransformParams params) { }
|
||||
}
|
||||
}
|
||||
|
||||
+62
-175
@@ -15,29 +15,18 @@
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.LauncherState.BACKGROUND_APP;
|
||||
import static com.android.launcher3.LauncherState.OVERVIEW;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
||||
import static com.android.launcher3.anim.Interpolators.INSTANT;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM;
|
||||
import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_RECENTS_TRANSLATE_X_ANIM;
|
||||
import static com.android.launcher3.uioverrides.states.QuickstepAtomicAnimationFactory.INDEX_SHELF_ANIM;
|
||||
import static com.android.quickstep.LauncherSwipeHandler.RECENTS_ATTACH_DURATION;
|
||||
import static com.android.quickstep.SysUINavigationMode.getMode;
|
||||
import static com.android.quickstep.SysUINavigationMode.hideShelfInTwoButtonLandscape;
|
||||
import static com.android.quickstep.util.LayoutUtils.getDefaultSwipeHeight;
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
|
||||
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.util.Log;
|
||||
import android.view.MotionEvent;
|
||||
import android.view.animation.Interpolator;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
@@ -61,9 +50,7 @@ import com.android.launcher3.userevent.nano.LauncherLogProto;
|
||||
import com.android.quickstep.SysUINavigationMode.Mode;
|
||||
import com.android.quickstep.util.ActivityInitListener;
|
||||
import com.android.quickstep.util.LayoutUtils;
|
||||
import com.android.quickstep.util.ShelfPeekAnim;
|
||||
import com.android.quickstep.util.ShelfPeekAnim.ShelfAnimState;
|
||||
import com.android.quickstep.views.LauncherRecentsView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.plugins.shared.LauncherOverlayManager;
|
||||
import com.android.systemui.shared.system.RemoteAnimationTargetCompat;
|
||||
@@ -75,12 +62,12 @@ import java.util.function.Predicate;
|
||||
* {@link BaseActivityInterface} for the in-launcher recents.
|
||||
*/
|
||||
public final class LauncherActivityInterface extends
|
||||
BaseActivityInterface<LauncherState, Launcher> {
|
||||
BaseActivityInterface<LauncherState, BaseQuickstepLauncher> {
|
||||
|
||||
public static final LauncherActivityInterface INSTANCE = new LauncherActivityInterface();
|
||||
|
||||
private LauncherActivityInterface() {
|
||||
super(true);
|
||||
super(true, OVERVIEW, BACKGROUND_APP);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -131,119 +118,43 @@ public final class LauncherActivityInterface extends
|
||||
@Override
|
||||
public AnimationFactory prepareRecentsUI(
|
||||
boolean activityVisible, Consumer<AnimatorPlaybackController> callback) {
|
||||
BaseQuickstepLauncher launcher = getCreatedActivity();
|
||||
final LauncherState startState = launcher.getStateManager().getState();
|
||||
|
||||
LauncherState resetState = startState;
|
||||
if (startState.shouldDisableRestore()) {
|
||||
resetState = launcher.getStateManager().getRestState();
|
||||
}
|
||||
launcher.getStateManager().setRestState(resetState);
|
||||
|
||||
launcher.getStateManager().goToState(BACKGROUND_APP, false);
|
||||
// Since all apps is not visible, we can safely reset the scroll position.
|
||||
// This ensures then the next swipe up to all-apps starts from scroll 0.
|
||||
launcher.getAppsView().reset(false /* animate */);
|
||||
|
||||
return new AnimationFactory() {
|
||||
private final ShelfPeekAnim mShelfAnim = launcher.getShelfPeekAnim();
|
||||
private boolean mIsAttachedToWindow;
|
||||
|
||||
@Override
|
||||
public void createActivityInterface(long transitionLength) {
|
||||
callback.accept(createBackgroundToOverviewAnim(launcher, transitionLength));
|
||||
// Creating the activity controller animation sometimes reapplies the launcher state
|
||||
// (because we set the animation as the current state animation), so we reapply the
|
||||
// attached state here as well to ensure recents is shown/hidden appropriately.
|
||||
if (SysUINavigationMode.getMode(launcher) == Mode.NO_BUTTON) {
|
||||
setRecentsAttachedToAppWindow(mIsAttachedToWindow, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionCancelled() {
|
||||
launcher.getStateManager().goToState(startState, false /* animate */);
|
||||
}
|
||||
|
||||
DefaultAnimationFactory factory = new DefaultAnimationFactory(callback) {
|
||||
@Override
|
||||
public void setShelfState(ShelfAnimState shelfState, Interpolator interpolator,
|
||||
long duration) {
|
||||
mShelfAnim.setShelfState(shelfState, interpolator, duration);
|
||||
mActivity.getShelfPeekAnim().setShelfState(shelfState, interpolator, duration);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecentsAttachedToAppWindow(boolean attached, boolean animate) {
|
||||
if (mIsAttachedToWindow == attached && animate) {
|
||||
return;
|
||||
}
|
||||
mIsAttachedToWindow = attached;
|
||||
LauncherRecentsView recentsView = launcher.getOverviewPanel();
|
||||
Animator fadeAnim = launcher.getStateManager()
|
||||
.createStateElementAnimation(
|
||||
INDEX_RECENTS_FADE_ANIM, attached ? 1 : 0);
|
||||
protected void createBackgroundToOverviewAnim(BaseQuickstepLauncher activity,
|
||||
PendingAnimation pa) {
|
||||
super.createBackgroundToOverviewAnim(activity, pa);
|
||||
|
||||
float fromTranslation = attached ? 1 : 0;
|
||||
float toTranslation = attached ? 0 : 1;
|
||||
launcher.getStateManager()
|
||||
.cancelStateElementAnimation(INDEX_RECENTS_TRANSLATE_X_ANIM);
|
||||
if (!recentsView.isShown() && animate) {
|
||||
ADJACENT_PAGE_OFFSET.set(recentsView, fromTranslation);
|
||||
} else {
|
||||
fromTranslation = ADJACENT_PAGE_OFFSET.get(recentsView);
|
||||
}
|
||||
if (!animate) {
|
||||
ADJACENT_PAGE_OFFSET.set(recentsView, toTranslation);
|
||||
} else {
|
||||
launcher.getStateManager().createStateElementAnimation(
|
||||
INDEX_RECENTS_TRANSLATE_X_ANIM,
|
||||
fromTranslation, toTranslation).start();
|
||||
if (!activity.getDeviceProfile().isVerticalBarLayout()
|
||||
&& SysUINavigationMode.getMode(activity) != Mode.NO_BUTTON) {
|
||||
// Don't animate the shelf when the mode is NO_BUTTON, because we
|
||||
// update it atomically.
|
||||
pa.add(activity.getStateManager().createStateElementAnimation(
|
||||
INDEX_SHELF_ANIM,
|
||||
BACKGROUND_APP.getVerticalProgress(activity),
|
||||
OVERVIEW.getVerticalProgress(activity)));
|
||||
}
|
||||
|
||||
fadeAnim.setInterpolator(attached ? INSTANT : ACCEL_2);
|
||||
fadeAnim.setDuration(animate ? RECENTS_ATTACH_DURATION : 0).start();
|
||||
// Animate the blur and wallpaper zoom
|
||||
float fromDepthRatio = BACKGROUND_APP.getDepth(activity);
|
||||
float toDepthRatio = OVERVIEW.getDepth(activity);
|
||||
pa.addFloat(getDepthController(),
|
||||
new ClampedDepthProperty(fromDepthRatio, toDepthRatio),
|
||||
fromDepthRatio, toDepthRatio, LINEAR);
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private AnimatorPlaybackController createBackgroundToOverviewAnim(
|
||||
Launcher activity, long transitionLength) {
|
||||
|
||||
PendingAnimation pa = new PendingAnimation(transitionLength * 2);
|
||||
|
||||
if (!activity.getDeviceProfile().isVerticalBarLayout()
|
||||
&& SysUINavigationMode.getMode(activity) != Mode.NO_BUTTON) {
|
||||
// Don't animate the shelf when the mode is NO_BUTTON, because we update it atomically.
|
||||
pa.add(activity.getStateManager().createStateElementAnimation(
|
||||
INDEX_SHELF_ANIM,
|
||||
BACKGROUND_APP.getVerticalProgress(activity),
|
||||
OVERVIEW.getVerticalProgress(activity)));
|
||||
}
|
||||
|
||||
// Animate the blur and wallpaper zoom
|
||||
float fromDepthRatio = BACKGROUND_APP.getDepth(activity);
|
||||
float toDepthRatio = OVERVIEW.getDepth(activity);
|
||||
pa.addFloat(getDepthController(), new ClampedDepthProperty(fromDepthRatio, toDepthRatio),
|
||||
fromDepthRatio, toDepthRatio, LINEAR);
|
||||
|
||||
|
||||
// Scale down recents from being full screen to being in overview.
|
||||
RecentsView recentsView = activity.getOverviewPanel();
|
||||
pa.addFloat(recentsView, SCALE_PROPERTY,
|
||||
BACKGROUND_APP.getOverviewScaleAndOffset(activity)[0],
|
||||
OVERVIEW.getOverviewScaleAndOffset(activity)[0],
|
||||
LINEAR);
|
||||
pa.addFloat(recentsView, FULLSCREEN_PROGRESS,
|
||||
BACKGROUND_APP.getOverviewFullscreenProgress(),
|
||||
OVERVIEW.getOverviewFullscreenProgress(),
|
||||
LINEAR);
|
||||
|
||||
AnimatorPlaybackController controller = pa.createPlaybackController();
|
||||
activity.getStateManager().setCurrentUserControlledAnimation(controller);
|
||||
|
||||
// Since we are changing the start position of the UI, reapply the state, at the end
|
||||
controller.setEndAction(() -> activity.getStateManager().goToState(
|
||||
controller.getInterpolatedProgress() > 0.5 ? OVERVIEW : BACKGROUND_APP, false));
|
||||
return controller;
|
||||
BaseQuickstepLauncher launcher = factory.initUI();
|
||||
// Since all apps is not visible, we can safely reset the scroll position.
|
||||
// This ensures then the next swipe up to all-apps starts from scroll 0.
|
||||
launcher.getAppsView().reset(false /* animate */);
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -252,6 +163,15 @@ public final class LauncherActivityInterface extends
|
||||
onInitListener.test(alreadyOnHome));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnDeferredActivityLaunchCallback(Runnable r) {
|
||||
Launcher launcher = getCreatedActivity();
|
||||
if (launcher == null) {
|
||||
return;
|
||||
}
|
||||
launcher.setOnDeferredActivityLaunchCallback(r);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public BaseQuickstepLauncher getCreatedActivity() {
|
||||
@@ -259,11 +179,13 @@ public final class LauncherActivityInterface extends
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@UiThread
|
||||
private Launcher getVisibleLauncher() {
|
||||
Launcher launcher = getCreatedActivity();
|
||||
return (launcher != null) && launcher.isStarted() && launcher.hasWindowFocus() ?
|
||||
launcher : null;
|
||||
@Override
|
||||
public DepthController getDepthController() {
|
||||
BaseQuickstepLauncher launcher = getCreatedActivity();
|
||||
if (launcher == null) {
|
||||
return null;
|
||||
}
|
||||
return launcher.getDepthController();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -274,6 +196,14 @@ public final class LauncherActivityInterface extends
|
||||
? launcher.getOverviewPanel() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@UiThread
|
||||
private Launcher getVisibleLauncher() {
|
||||
Launcher launcher = getCreatedActivity();
|
||||
return (launcher != null) && launcher.isStarted() && launcher.hasWindowFocus()
|
||||
? launcher : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean switchToRecentsIfVisible(Runnable onCompleteCallback) {
|
||||
if (TestProtocol.sDebugTracing) {
|
||||
@@ -293,15 +223,6 @@ public final class LauncherActivityInterface extends
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setHintUserWillBeActive() {
|
||||
getCreatedActivity().setHintUserWillBeActive();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
|
||||
return deviceState.isInDeferredGestureRegion(ev);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rect getOverviewWindowBounds(Rect homeBounds, RemoteAnimationTargetCompat target) {
|
||||
@@ -313,6 +234,16 @@ public final class LauncherActivityInterface extends
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateOverviewPredictionState() {
|
||||
Launcher launcher = getCreatedActivity();
|
||||
if (launcher == null) {
|
||||
return;
|
||||
}
|
||||
PredictionUiStateManager.INSTANCE.get(launcher).switchClient(
|
||||
PredictionUiStateManager.Client.OVERVIEW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getContainerType() {
|
||||
final Launcher launcher = getVisibleLauncher();
|
||||
@@ -350,51 +281,6 @@ public final class LauncherActivityInterface extends
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnDeferredActivityLaunchCallback(Runnable r) {
|
||||
Launcher launcher = getCreatedActivity();
|
||||
if (launcher == null) {
|
||||
return;
|
||||
}
|
||||
launcher.setOnDeferredActivityLaunchCallback(r);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateOverviewPredictionState() {
|
||||
Launcher launcher = getCreatedActivity();
|
||||
if (launcher == null) {
|
||||
return;
|
||||
}
|
||||
PredictionUiStateManager.INSTANCE.get(launcher).switchClient(
|
||||
PredictionUiStateManager.Client.OVERVIEW);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public DepthController getDepthController() {
|
||||
BaseQuickstepLauncher launcher = getCreatedActivity();
|
||||
if (launcher == null) {
|
||||
return null;
|
||||
}
|
||||
return launcher.getDepthController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getMultiWindowSize(Context context, DeviceProfile dp, PointF out) {
|
||||
DeviceProfile fullDp = dp.getFullScreenProfile();
|
||||
// Use availableWidthPx and availableHeightPx instead of widthPx and heightPx to
|
||||
// account for system insets
|
||||
out.set(fullDp.availableWidthPx, fullDp.availableHeightPx);
|
||||
float halfDividerSize = context.getResources()
|
||||
.getDimension(R.dimen.multi_window_task_divider_size) / 2;
|
||||
|
||||
if (fullDp.isLandscape) {
|
||||
out.x = out.x / 2 - halfDividerSize;
|
||||
} else {
|
||||
out.y = out.y / 2 - halfDividerSize;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected float getExtraSpace(Context context, DeviceProfile dp,
|
||||
PagedOrientationHandler orientationHandler) {
|
||||
@@ -426,4 +312,5 @@ public final class LauncherActivityInterface extends
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.quickstep;
|
||||
|
||||
import static com.android.launcher3.LauncherState.NORMAL;
|
||||
|
||||
import android.animation.AnimatorSet;
|
||||
import android.content.Context;
|
||||
import android.graphics.RectF;
|
||||
import android.os.UserHandle;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.android.launcher3.BaseQuickstepLauncher;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.views.FloatingIconView;
|
||||
import com.android.quickstep.util.StaggeredWorkspaceAnim;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.system.InputConsumerController;
|
||||
|
||||
/**
|
||||
* Temporary class to allow easier refactoring
|
||||
*/
|
||||
public class LauncherSwipeHandlerV2 extends
|
||||
BaseSwipeUpHandlerV2<BaseQuickstepLauncher, RecentsView> {
|
||||
|
||||
public LauncherSwipeHandlerV2(Context context, RecentsAnimationDeviceState deviceState,
|
||||
TaskAnimationManager taskAnimationManager, GestureState gestureState, long touchTimeMs,
|
||||
boolean continuingLastGesture, InputConsumerController inputConsumer) {
|
||||
super(context, deviceState, taskAnimationManager, gestureState, touchTimeMs,
|
||||
continuingLastGesture, inputConsumer);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected HomeAnimationFactory createHomeAnimationFactory(long duration) {
|
||||
HomeAnimationFactory homeAnimFactory;
|
||||
if (mActivity != null) {
|
||||
final TaskView runningTaskView = mRecentsView.getRunningTaskView();
|
||||
final View workspaceView;
|
||||
if (runningTaskView != null
|
||||
&& runningTaskView.getTask().key.getComponent() != null) {
|
||||
workspaceView = mActivity.getWorkspace().getFirstMatchForAppClose(
|
||||
runningTaskView.getTask().key.getComponent().getPackageName(),
|
||||
UserHandle.of(runningTaskView.getTask().key.userId));
|
||||
} else {
|
||||
workspaceView = null;
|
||||
}
|
||||
final RectF iconLocation = new RectF();
|
||||
boolean canUseWorkspaceView =
|
||||
workspaceView != null && workspaceView.isAttachedToWindow();
|
||||
FloatingIconView floatingIconView = canUseWorkspaceView
|
||||
? FloatingIconView.getFloatingIconView(mActivity, workspaceView,
|
||||
true /* hideOriginal */, iconLocation, false /* isOpening */)
|
||||
: null;
|
||||
|
||||
mActivity.getRootView().setForceHideBackArrow(true);
|
||||
mActivity.setHintUserWillBeActive();
|
||||
|
||||
homeAnimFactory = new HomeAnimationFactory(floatingIconView) {
|
||||
|
||||
@Override
|
||||
public RectF getWindowTargetRect() {
|
||||
if (canUseWorkspaceView) {
|
||||
return iconLocation;
|
||||
} else {
|
||||
return super.getWindowTargetRect();
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
// Return an empty APC here since we have an non-user controlled animation
|
||||
// to home.
|
||||
long accuracy = 2 * Math.max(mDp.widthPx, mDp.heightPx);
|
||||
return mActivity.getStateManager().createAnimationToNewWorkspace(
|
||||
NORMAL, accuracy, 0 /* animComponents */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void playAtomicAnimation(float velocity) {
|
||||
new StaggeredWorkspaceAnim(mActivity, velocity,
|
||||
true /* animateOverviewScrim */).start();
|
||||
}
|
||||
};
|
||||
|
||||
} else {
|
||||
homeAnimFactory = new HomeAnimationFactory(null) {
|
||||
@Override
|
||||
public AnimatorPlaybackController createActivityAnimationToHome() {
|
||||
return AnimatorPlaybackController.wrap(new AnimatorSet(), duration);
|
||||
}
|
||||
};
|
||||
mStateCallback.addChangeListener(STATE_LAUNCHER_PRESENT | STATE_HANDLER_INVALIDATED,
|
||||
isPresent -> mRecentsView.startHome());
|
||||
}
|
||||
return homeAnimFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finishRecentsControllerToHome(Runnable callback) {
|
||||
mRecentsAnimationController.finish(
|
||||
true /* toRecents */, callback, true /* sendUserLeaveHint */);
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@ import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.Interpolators;
|
||||
import com.android.launcher3.compat.AccessibilityManagerCompat;
|
||||
import com.android.launcher3.statemanager.StateManager;
|
||||
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
|
||||
import com.android.launcher3.statemanager.StateManager.StateHandler;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.launcher3.util.ActivityTracker;
|
||||
@@ -57,6 +58,7 @@ import com.android.quickstep.fallback.FallbackRecentsStateController;
|
||||
import com.android.quickstep.fallback.FallbackRecentsView;
|
||||
import com.android.quickstep.fallback.RecentsRootView;
|
||||
import com.android.quickstep.fallback.RecentsState;
|
||||
import com.android.quickstep.util.RecentsAtomicAnimationFactory;
|
||||
import com.android.quickstep.views.OverviewActionsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.ThumbnailData;
|
||||
@@ -345,6 +347,11 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
|
||||
dumpMisc(prefix + "\t", writer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AtomicAnimationFactory<RecentsState> createAtomicAnimationFactory() {
|
||||
return new RecentsAtomicAnimationFactory<>(this, 0);
|
||||
}
|
||||
|
||||
private AnimatorListenerAdapter resetStateListener() {
|
||||
return new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
|
||||
+7
-8
@@ -85,7 +85,6 @@ import com.android.quickstep.util.ActiveGestureLog;
|
||||
import com.android.quickstep.util.AssistantUtilities;
|
||||
import com.android.quickstep.util.ProtoTracer;
|
||||
import com.android.quickstep.util.SplitScreenBounds;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.systemui.plugins.OverscrollPlugin;
|
||||
import com.android.systemui.plugins.PluginListener;
|
||||
import com.android.systemui.shared.recents.IOverviewProxy;
|
||||
@@ -833,16 +832,16 @@ public class TouchInteractionService extends Service implements PluginListener<O
|
||||
}
|
||||
}
|
||||
|
||||
private BaseSwipeUpHandler createLauncherSwipeHandler(GestureState gestureState,
|
||||
long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask) {
|
||||
return new LauncherSwipeHandler(this, mDeviceState, mTaskAnimationManager,
|
||||
private BaseSwipeUpHandler createLauncherSwipeHandler(
|
||||
GestureState gestureState, long touchTimeMs, boolean continuingLastGesture) {
|
||||
return new LauncherSwipeHandlerV2(this, mDeviceState, mTaskAnimationManager,
|
||||
gestureState, touchTimeMs, continuingLastGesture, mInputConsumer);
|
||||
}
|
||||
|
||||
private BaseSwipeUpHandler createFallbackSwipeHandler(GestureState gestureState,
|
||||
long touchTimeMs, boolean continuingLastGesture, boolean isLikelyToStartNewTask) {
|
||||
return new FallbackSwipeHandler(this, mDeviceState, gestureState,
|
||||
mInputConsumer, isLikelyToStartNewTask, continuingLastGesture);
|
||||
private BaseSwipeUpHandler createFallbackSwipeHandler(
|
||||
GestureState gestureState, long touchTimeMs, boolean continuingLastGesture) {
|
||||
return new FallbackSwipeHandler(this, mDeviceState, mTaskAnimationManager,
|
||||
gestureState, touchTimeMs, continuingLastGesture, mInputConsumer);
|
||||
}
|
||||
|
||||
protected boolean shouldNotifyBackGesture() {
|
||||
|
||||
+43
-8
@@ -24,11 +24,13 @@ import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.util.AttributeSet;
|
||||
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.statemanager.StateManager.StateListener;
|
||||
import com.android.quickstep.FallbackActivityInterface;
|
||||
import com.android.quickstep.RecentsActivity;
|
||||
import com.android.quickstep.views.OverviewActionsView;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
import com.android.quickstep.views.TaskView;
|
||||
import com.android.systemui.shared.recents.model.Task;
|
||||
import com.android.systemui.shared.recents.model.Task.TaskKey;
|
||||
|
||||
@@ -38,7 +40,7 @@ import java.util.ArrayList;
|
||||
public class FallbackRecentsView extends RecentsView<RecentsActivity>
|
||||
implements StateListener<RecentsState> {
|
||||
|
||||
private RunningTaskInfo mRunningTaskInfo;
|
||||
private RunningTaskInfo mHomeTaskInfo;
|
||||
|
||||
public FallbackRecentsView(Context context, AttributeSet attrs) {
|
||||
this(context, attrs, 0);
|
||||
@@ -67,16 +69,40 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity>
|
||||
return false;
|
||||
}
|
||||
|
||||
public void onGestureAnimationStart(RunningTaskInfo runningTaskInfo) {
|
||||
mRunningTaskInfo = runningTaskInfo;
|
||||
onGestureAnimationStart(runningTaskInfo == null ? -1 : runningTaskInfo.taskId);
|
||||
/**
|
||||
* When starting gesture interaction from home, we add a temporary invisible tile corresponding
|
||||
* to the home task. This allows us to handle quick-switch similarly to a quick-switching
|
||||
* from a foreground task.
|
||||
*/
|
||||
public void onGestureAnimationStartOnHome(RunningTaskInfo homeTaskInfo) {
|
||||
mHomeTaskInfo = homeTaskInfo;
|
||||
onGestureAnimationStart(homeTaskInfo == null ? -1 : homeTaskInfo.taskId);
|
||||
}
|
||||
|
||||
/**
|
||||
* When the gesture ends and recents view become interactive, we also remove the temporary
|
||||
* invisible tile added for the home task. This also pushes the remaining tiles back
|
||||
* to the center.
|
||||
*/
|
||||
@Override
|
||||
public void onGestureAnimationEnd() {
|
||||
super.onGestureAnimationEnd();
|
||||
if (mHomeTaskInfo != null) {
|
||||
TaskView tv = getTaskView(mHomeTaskInfo.taskId);
|
||||
if (tv != null) {
|
||||
PendingAnimation pa = createTaskDismissAnimation(tv, true, false, 150);
|
||||
pa.addEndListener(e -> setCurrentTask(-1));
|
||||
runDismissAnimation(pa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrentTask(int runningTaskId) {
|
||||
super.setCurrentTask(runningTaskId);
|
||||
if (mRunningTaskInfo != null && mRunningTaskInfo.taskId != runningTaskId) {
|
||||
mRunningTaskInfo = null;
|
||||
if (mHomeTaskInfo != null && mHomeTaskInfo.taskId != runningTaskId) {
|
||||
mHomeTaskInfo = null;
|
||||
setRunningTaskHidden(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +111,7 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity>
|
||||
// When quick-switching on 3p-launcher, we add a "dummy" tile corresponding to Launcher
|
||||
// as well. This tile is never shown as we have setCurrentTaskHidden, but allows use to
|
||||
// track the index of the next task appropriately, as if we are switching on any other app.
|
||||
if (mRunningTaskInfo != null && mRunningTaskInfo.taskId == mRunningTaskId) {
|
||||
if (mHomeTaskInfo != null && mHomeTaskInfo.taskId == mRunningTaskId) {
|
||||
// Check if the task list has running task
|
||||
boolean found = false;
|
||||
for (Task t : tasks) {
|
||||
@@ -97,13 +123,22 @@ public class FallbackRecentsView extends RecentsView<RecentsActivity>
|
||||
if (!found) {
|
||||
ArrayList<Task> newList = new ArrayList<>(tasks.size() + 1);
|
||||
newList.addAll(tasks);
|
||||
newList.add(Task.from(new TaskKey(mRunningTaskInfo), mRunningTaskInfo, false));
|
||||
newList.add(Task.from(new TaskKey(mHomeTaskInfo), mHomeTaskInfo, false));
|
||||
tasks = newList;
|
||||
}
|
||||
}
|
||||
super.applyLoadPlan(tasks);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRunningTaskHidden(boolean isHidden) {
|
||||
if (mHomeTaskInfo != null) {
|
||||
// Always keep the home task hidden
|
||||
isHidden = true;
|
||||
}
|
||||
super.setRunningTaskHidden(isHidden);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModalStateEnabled(boolean isModalState) {
|
||||
super.setModalStateEnabled(isModalState);
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ import static android.view.MotionEvent.ACTION_UP;
|
||||
|
||||
import static com.android.launcher3.Utilities.squaredHypot;
|
||||
import static com.android.launcher3.Utilities.squaredTouchSlop;
|
||||
import static com.android.quickstep.LauncherSwipeHandler.MIN_PROGRESS_FOR_OVERVIEW;
|
||||
import static com.android.quickstep.BaseSwipeUpHandlerV2.MIN_PROGRESS_FOR_OVERVIEW;
|
||||
import static com.android.quickstep.MultiStateCallback.DEBUG_STATES;
|
||||
import static com.android.quickstep.util.ActiveGestureLog.INTENT_EXTRA_LOG_TRACE_ID;
|
||||
|
||||
|
||||
+4
-6
@@ -207,7 +207,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
// Start the window animation on down to give more time for launcher to draw if the
|
||||
// user didn't start the gesture over the back button
|
||||
if (!mIsDeferredDownTarget) {
|
||||
startTouchTrackingForWindowAnimation(ev.getEventTime(), false);
|
||||
startTouchTrackingForWindowAnimation(ev.getEventTime());
|
||||
}
|
||||
|
||||
TraceHelper.INSTANCE.endSection(traceToken);
|
||||
@@ -275,8 +275,7 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
if (mIsDeferredDownTarget) {
|
||||
// Deferred gesture, start the animation and gesture tracking once
|
||||
// we pass the actual touch slop
|
||||
startTouchTrackingForWindowAnimation(
|
||||
ev.getEventTime(), isLikelyToStartNewTask);
|
||||
startTouchTrackingForWindowAnimation(ev.getEventTime());
|
||||
}
|
||||
if (!mPassedWindowMoveSlop) {
|
||||
mPassedWindowMoveSlop = true;
|
||||
@@ -326,12 +325,11 @@ public class OtherActivityInputConsumer extends ContextWrapper implements InputC
|
||||
mInteractionHandler.onGestureStarted();
|
||||
}
|
||||
|
||||
private void startTouchTrackingForWindowAnimation(
|
||||
long touchTimeMs, boolean isLikelyToStartNewTask) {
|
||||
private void startTouchTrackingForWindowAnimation(long touchTimeMs) {
|
||||
ActiveGestureLog.INSTANCE.addLog("startRecentsAnimation");
|
||||
|
||||
mInteractionHandler = mHandlerFactory.newHandler(mGestureState, touchTimeMs,
|
||||
mTaskAnimationManager.isRecentsAnimationRunning(), isLikelyToStartNewTask);
|
||||
mTaskAnimationManager.isRecentsAnimationRunning());
|
||||
mInteractionHandler.setGestureEndCallback(this::onInteractionGestureFinished);
|
||||
mMotionPauseDetector.setOnMotionPauseListener(mInteractionHandler::onMotionPauseChanged);
|
||||
Intent intent = new Intent(mInteractionHandler.getLaunchIntent());
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2020 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.quickstep.util;
|
||||
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.animation.ObjectAnimator;
|
||||
|
||||
import com.android.launcher3.anim.SpringAnimationBuilder;
|
||||
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
import com.android.quickstep.views.RecentsView;
|
||||
|
||||
public class RecentsAtomicAnimationFactory<ACTIVITY_TYPE extends StatefulActivity, STATE_TYPE>
|
||||
extends AtomicAnimationFactory<STATE_TYPE> {
|
||||
|
||||
public static final int INDEX_RECENTS_FADE_ANIM = AtomicAnimationFactory.NEXT_INDEX + 0;
|
||||
public static final int INDEX_RECENTS_TRANSLATE_X_ANIM = AtomicAnimationFactory.NEXT_INDEX + 1;
|
||||
|
||||
private static final int MY_ANIM_COUNT = 2;
|
||||
protected static final int NEXT_INDEX = AtomicAnimationFactory.NEXT_INDEX + MY_ANIM_COUNT;
|
||||
|
||||
protected final ACTIVITY_TYPE mActivity;
|
||||
|
||||
/**
|
||||
* @param extraAnims number of animations supported by the subclass. This should not include
|
||||
* the 2 animations supported by this class.
|
||||
*/
|
||||
public RecentsAtomicAnimationFactory(ACTIVITY_TYPE activity, int extraAnims) {
|
||||
super(MY_ANIM_COUNT + extraAnims);
|
||||
mActivity = activity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Animator createStateElementAnimation(int index, float... values) {
|
||||
switch (index) {
|
||||
case INDEX_RECENTS_FADE_ANIM:
|
||||
return ObjectAnimator.ofFloat(mActivity.getOverviewPanel(),
|
||||
RecentsView.CONTENT_ALPHA, values);
|
||||
case INDEX_RECENTS_TRANSLATE_X_ANIM: {
|
||||
RecentsView rv = mActivity.getOverviewPanel();
|
||||
return new SpringAnimationBuilder(mActivity)
|
||||
.setMinimumVisibleChange(1f / rv.getPageOffsetScale())
|
||||
.setDampingRatio(0.8f)
|
||||
.setStiffness(250)
|
||||
.setValues(values)
|
||||
.build(rv, ADJACENT_PAGE_OFFSET);
|
||||
}
|
||||
default:
|
||||
return super.createStateElementAnimation(index, values);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -47,24 +47,21 @@ public class ClearAllButton extends Button implements PageCallbacks {
|
||||
private boolean mIsRtl;
|
||||
|
||||
private int mScrollOffset;
|
||||
private RecentsView mParent;
|
||||
|
||||
public ClearAllButton(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
mIsRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
|
||||
super.onLayout(changed, left, top, right, bottom);
|
||||
PagedOrientationHandler orientationHandler = mParent.getPagedOrientationHandler();
|
||||
mScrollOffset = orientationHandler.getClearAllScrollOffset(mParent, mIsRtl);
|
||||
PagedOrientationHandler orientationHandler = getRecentsView().getPagedOrientationHandler();
|
||||
mScrollOffset = orientationHandler.getClearAllScrollOffset(getRecentsView(), mIsRtl);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
mParent = (RecentsView) getParent();
|
||||
mIsRtl = getLayoutDirection() == LAYOUT_DIRECTION_RTL;
|
||||
private RecentsView getRecentsView() {
|
||||
return (RecentsView) getParent();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,7 +91,7 @@ public class ClearAllButton extends Button implements PageCallbacks {
|
||||
|
||||
@Override
|
||||
public void onPageScroll(ScrollState scrollState) {
|
||||
PagedOrientationHandler orientationHandler = mParent.getPagedOrientationHandler();
|
||||
PagedOrientationHandler orientationHandler = getRecentsView().getPagedOrientationHandler();
|
||||
float orientationSize = orientationHandler.getPrimaryValue(getWidth(), getHeight());
|
||||
if (orientationSize == 0) {
|
||||
return;
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
package com.android.quickstep.views;
|
||||
|
||||
import static android.view.Surface.ROTATION_0;
|
||||
import static android.view.View.MeasureSpec.EXACTLY;
|
||||
import static android.view.View.MeasureSpec.makeMeasureSpec;
|
||||
|
||||
import static com.android.launcher3.BaseActivity.STATE_HANDLER_INVISIBILITY_FLAGS;
|
||||
import static com.android.launcher3.InvariantDeviceProfile.CHANGE_FLAG_ICON_PARAMS;
|
||||
@@ -1080,9 +1082,9 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
* Called when a gesture from an app has finished.
|
||||
*/
|
||||
public void onGestureAnimationEnd() {
|
||||
setOnScrollChangeListener(null);
|
||||
setEnableFreeScroll(true);
|
||||
setEnableDrawingLiveTile(true);
|
||||
setOnScrollChangeListener(null);
|
||||
if (!ENABLE_QUICKSTEP_LIVE_TILE.get()) {
|
||||
setRunningTaskViewShowScreenshot(true);
|
||||
}
|
||||
@@ -1113,6 +1115,12 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
false, true, false, false, new ActivityManager.TaskDescription(), 0,
|
||||
new ComponentName("", ""), false);
|
||||
taskView.bind(mTmpRunningTask, mOrientationState);
|
||||
|
||||
// Measure and layout immediately so that the scroll values is updated instantly
|
||||
// as the user might be quick-switching
|
||||
measure(makeMeasureSpec(getMeasuredWidth(), EXACTLY),
|
||||
makeMeasureSpec(getMeasuredHeight(), EXACTLY));
|
||||
layout(getLeft(), getTop(), getRight(), getBottom());
|
||||
}
|
||||
|
||||
boolean runningTaskTileHidden = mRunningTaskTileHidden;
|
||||
@@ -1489,7 +1497,7 @@ public abstract class RecentsView<T extends BaseActivity> extends PagedView impl
|
||||
return true;
|
||||
}
|
||||
|
||||
private void runDismissAnimation(PendingAnimation pendingAnim) {
|
||||
protected void runDismissAnimation(PendingAnimation pendingAnim) {
|
||||
AnimatorPlaybackController controller = pendingAnim.createPlaybackController();
|
||||
controller.dispatchOnStart();
|
||||
controller.setEndAction(() -> pendingAnim.finish(true, Touch.SWIPE));
|
||||
|
||||
@@ -15,15 +15,24 @@
|
||||
*/
|
||||
package com.android.quickstep;
|
||||
|
||||
import static com.android.launcher3.LauncherAnimUtils.SCALE_PROPERTY;
|
||||
import static com.android.launcher3.anim.Interpolators.ACCEL_2;
|
||||
import static com.android.launcher3.anim.Interpolators.INSTANT;
|
||||
import static com.android.launcher3.anim.Interpolators.LINEAR;
|
||||
import static com.android.launcher3.config.FeatureFlags.ENABLE_OVERVIEW_ACTIONS;
|
||||
import static com.android.quickstep.BaseSwipeUpHandlerV2.RECENTS_ATTACH_DURATION;
|
||||
import static com.android.quickstep.SysUINavigationMode.getMode;
|
||||
import static com.android.quickstep.SysUINavigationMode.hideShelfInTwoButtonLandscape;
|
||||
import static com.android.quickstep.SysUINavigationMode.removeShelfFromOverview;
|
||||
import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_FADE_ANIM;
|
||||
import static com.android.quickstep.util.RecentsAtomicAnimationFactory.INDEX_RECENTS_TRANSLATE_X_ANIM;
|
||||
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_OFFSET;
|
||||
import static com.android.quickstep.views.RecentsView.FULLSCREEN_PROGRESS;
|
||||
|
||||
import android.animation.Animator;
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.PointF;
|
||||
import android.graphics.Rect;
|
||||
import android.os.Build;
|
||||
import android.view.MotionEvent;
|
||||
@@ -35,6 +44,7 @@ import androidx.annotation.UiThread;
|
||||
import com.android.launcher3.DeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.anim.AnimatorPlaybackController;
|
||||
import com.android.launcher3.anim.PendingAnimation;
|
||||
import com.android.launcher3.statehandlers.DepthController;
|
||||
import com.android.launcher3.statemanager.BaseState;
|
||||
import com.android.launcher3.statemanager.StatefulActivity;
|
||||
@@ -58,11 +68,15 @@ import java.util.function.Predicate;
|
||||
public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_TYPE>,
|
||||
ACTIVITY_TYPE extends StatefulActivity<STATE_TYPE>> {
|
||||
|
||||
private final PointF mTempPoint = new PointF();
|
||||
public final boolean rotationSupportedByActivity;
|
||||
|
||||
protected BaseActivityInterface(boolean rotationSupportedByActivity) {
|
||||
private final STATE_TYPE mOverviewState, mBackgroundState;
|
||||
|
||||
protected BaseActivityInterface(boolean rotationSupportedByActivity,
|
||||
STATE_TYPE overviewState, STATE_TYPE backgroundState) {
|
||||
this.rotationSupportedByActivity = rotationSupportedByActivity;
|
||||
mOverviewState = overviewState;
|
||||
mBackgroundState = backgroundState;
|
||||
}
|
||||
|
||||
public void onTransitionCancelled(boolean activityVisible) {
|
||||
@@ -87,7 +101,7 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
activity.getStateManager().reapplyState();
|
||||
}
|
||||
|
||||
public void onSwipeUpToHomeComplete() { }
|
||||
public abstract void onSwipeUpToHomeComplete();
|
||||
|
||||
public abstract void onAssistantVisibilityChanged(float visibility);
|
||||
|
||||
@@ -133,7 +147,7 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
public abstract boolean allowMinimizeSplitScreen();
|
||||
|
||||
public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
|
||||
return true;
|
||||
return deviceState.isInDeferredGestureRegion(ev);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,13 +191,6 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
recentsView.switchToScreenshot(thumbnailData, runnable);
|
||||
}
|
||||
|
||||
public void setHintUserWillBeActive() {}
|
||||
|
||||
/**
|
||||
* Sets the expected window size in multi-window mode
|
||||
*/
|
||||
public abstract void getMultiWindowSize(Context context, DeviceProfile dp, PointF out);
|
||||
|
||||
/**
|
||||
* Calculates the taskView size for the provided device configuration
|
||||
*/
|
||||
@@ -259,7 +266,7 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
/**
|
||||
* Calculates the modal taskView size for the provided device configuration
|
||||
*/
|
||||
public void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect) {
|
||||
public final void calculateModalTaskSize(Context context, DeviceProfile dp, Rect outRect) {
|
||||
float paddingHorz = context.getResources().getDimension(dp.isMultiWindowMode
|
||||
? R.dimen.multi_window_task_card_horz_space
|
||||
: dp.isVerticalBarLayout()
|
||||
@@ -273,7 +280,7 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
}
|
||||
|
||||
/** Gets the space that the overview actions will take, including margins. */
|
||||
public float getOverviewActionsHeight(Context context) {
|
||||
public final float getOverviewActionsHeight(Context context) {
|
||||
Resources res = context.getResources();
|
||||
float actionsBottomMargin = 0;
|
||||
if (getMode(context) == Mode.THREE_BUTTONS) {
|
||||
@@ -290,8 +297,6 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
|
||||
public interface AnimationFactory {
|
||||
|
||||
default void onRemoteAnimationReceived(RemoteAnimationTargets targets) { }
|
||||
|
||||
void createActivityInterface(long transitionLength);
|
||||
|
||||
default void onTransitionCancelled() { }
|
||||
@@ -307,6 +312,97 @@ public abstract class BaseActivityInterface<STATE_TYPE extends BaseState<STATE_T
|
||||
default void setRecentsAttachedToAppWindow(boolean attached, boolean animate) { }
|
||||
}
|
||||
|
||||
class DefaultAnimationFactory implements AnimationFactory {
|
||||
|
||||
protected final ACTIVITY_TYPE mActivity;
|
||||
private final STATE_TYPE mStartState;
|
||||
private final Consumer<AnimatorPlaybackController> mCallback;
|
||||
|
||||
private boolean mIsAttachedToWindow;
|
||||
|
||||
DefaultAnimationFactory(Consumer<AnimatorPlaybackController> callback) {
|
||||
mCallback = callback;
|
||||
|
||||
mActivity = getCreatedActivity();
|
||||
mStartState = mActivity.getStateManager().getState();
|
||||
}
|
||||
|
||||
protected ACTIVITY_TYPE initUI() {
|
||||
STATE_TYPE resetState = mStartState;
|
||||
if (mStartState.shouldDisableRestore()) {
|
||||
resetState = mActivity.getStateManager().getRestState();
|
||||
}
|
||||
mActivity.getStateManager().setRestState(resetState);
|
||||
mActivity.getStateManager().goToState(mBackgroundState, false);
|
||||
return mActivity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createActivityInterface(long transitionLength) {
|
||||
PendingAnimation pa = new PendingAnimation(transitionLength * 2);
|
||||
createBackgroundToOverviewAnim(mActivity, pa);
|
||||
AnimatorPlaybackController controller = pa.createPlaybackController();
|
||||
mActivity.getStateManager().setCurrentUserControlledAnimation(controller);
|
||||
|
||||
// Since we are changing the start position of the UI, reapply the state, at the end
|
||||
controller.setEndAction(() -> mActivity.getStateManager().goToState(
|
||||
controller.getInterpolatedProgress() > 0.5 ? mOverviewState : mBackgroundState,
|
||||
false));
|
||||
mCallback.accept(controller);
|
||||
|
||||
// Creating the activity controller animation sometimes reapplies the launcher state
|
||||
// (because we set the animation as the current state animation), so we reapply the
|
||||
// attached state here as well to ensure recents is shown/hidden appropriately.
|
||||
if (SysUINavigationMode.getMode(mActivity) == Mode.NO_BUTTON) {
|
||||
setRecentsAttachedToAppWindow(mIsAttachedToWindow, false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTransitionCancelled() {
|
||||
mActivity.getStateManager().goToState(mStartState, false /* animate */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setRecentsAttachedToAppWindow(boolean attached, boolean animate) {
|
||||
if (mIsAttachedToWindow == attached && animate) {
|
||||
return;
|
||||
}
|
||||
mIsAttachedToWindow = attached;
|
||||
RecentsView recentsView = mActivity.getOverviewPanel();
|
||||
Animator fadeAnim = mActivity.getStateManager()
|
||||
.createStateElementAnimation(INDEX_RECENTS_FADE_ANIM, attached ? 1 : 0);
|
||||
|
||||
float fromTranslation = attached ? 1 : 0;
|
||||
float toTranslation = attached ? 0 : 1;
|
||||
mActivity.getStateManager()
|
||||
.cancelStateElementAnimation(INDEX_RECENTS_TRANSLATE_X_ANIM);
|
||||
if (!recentsView.isShown() && animate) {
|
||||
ADJACENT_PAGE_OFFSET.set(recentsView, fromTranslation);
|
||||
} else {
|
||||
fromTranslation = ADJACENT_PAGE_OFFSET.get(recentsView);
|
||||
}
|
||||
if (!animate) {
|
||||
ADJACENT_PAGE_OFFSET.set(recentsView, toTranslation);
|
||||
} else {
|
||||
mActivity.getStateManager().createStateElementAnimation(
|
||||
INDEX_RECENTS_TRANSLATE_X_ANIM,
|
||||
fromTranslation, toTranslation).start();
|
||||
}
|
||||
|
||||
fadeAnim.setInterpolator(attached ? INSTANT : ACCEL_2);
|
||||
fadeAnim.setDuration(animate ? RECENTS_ATTACH_DURATION : 0).start();
|
||||
}
|
||||
|
||||
protected void createBackgroundToOverviewAnim(ACTIVITY_TYPE activity, PendingAnimation pa) {
|
||||
// Scale down recents from being full screen to being in overview.
|
||||
RecentsView recentsView = activity.getOverviewPanel();
|
||||
pa.addFloat(recentsView, SCALE_PROPERTY,
|
||||
recentsView.getMaxScaleForFullScreen(), 1, LINEAR);
|
||||
pa.addFloat(recentsView, FULLSCREEN_PROGRESS, 1, 0, LINEAR);
|
||||
}
|
||||
}
|
||||
|
||||
protected static boolean showOverviewActions(Context context) {
|
||||
return ENABLE_OVERVIEW_ACTIONS.get() && removeShelfFromOverview(context);
|
||||
}
|
||||
|
||||
@@ -554,6 +554,8 @@ public class StateManager<STATE_TYPE extends BaseState<STATE_TYPE>> {
|
||||
*/
|
||||
public static class AtomicAnimationFactory<STATE_TYPE> {
|
||||
|
||||
protected static final int NEXT_INDEX = 0;
|
||||
|
||||
private final Animator[] mStateElementAnimators;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user