Merge "Reset split selection state when swiping to home" into udc-qpr-dev

This commit is contained in:
Vinit Nayak
2023-07-06 22:14:41 +00:00
committed by Android (Google) Code Review
9 changed files with 122 additions and 68 deletions
@@ -24,33 +24,26 @@ import static com.android.launcher3.LauncherState.QUICK_SWITCH_FROM_HOME;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_MODAL;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SCALE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SPLIT_SELECT_FLOATING_TASK_TRANSLATE_OFFSCREEN;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_X;
import static com.android.launcher3.states.StateAnimationConfig.ANIM_OVERVIEW_TRANSLATE_Y;
import static com.android.launcher3.states.StateAnimationConfig.SKIP_OVERVIEW;
import static com.android.quickstep.views.FloatingTaskView.PRIMARY_TRANSLATE_OFFSCREEN;
import static com.android.quickstep.views.RecentsView.ADJACENT_PAGE_HORIZONTAL_OFFSET;
import static com.android.quickstep.views.RecentsView.RECENTS_GRID_PROGRESS;
import static com.android.quickstep.views.RecentsView.RECENTS_SCALE_PROPERTY;
import static com.android.quickstep.views.RecentsView.TASK_SECONDARY_TRANSLATION;
import static com.android.quickstep.views.RecentsView.TASK_THUMBNAIL_SPLASH_ALPHA;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.FloatProperty;
import android.view.animation.Interpolator;
import androidx.annotation.NonNull;
import com.android.launcher3.LauncherState;
import com.android.launcher3.Utilities;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.dragndrop.DragLayer;
import com.android.launcher3.statemanager.StateManager.StateHandler;
import com.android.launcher3.states.StateAnimationConfig;
import com.android.quickstep.views.FloatingTaskView;
import com.android.quickstep.views.RecentsView;
/**
@@ -115,49 +108,18 @@ public abstract class BaseRecentsViewStateController<T extends RecentsView>
config.getInterpolator(ANIM_OVERVIEW_TRANSLATE_Y, LINEAR));
boolean exitingOverview = !FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()
|| !toState.overviewUi;
&& !toState.overviewUi;
if (mRecentsView.isSplitSelectionActive() && exitingOverview) {
// TODO (b/238651489): Refactor state management to avoid need for double check
FloatingTaskView floatingTask = mRecentsView.getFirstFloatingTaskView();
if (floatingTask != null) {
// We are in split selection state currently, transitioning to another state
DragLayer dragLayer = mLauncher.getDragLayer();
RectF onScreenRectF = new RectF();
Utilities.getBoundsForViewInDragLayer(mLauncher.getDragLayer(), floatingTask,
new Rect(0, 0, floatingTask.getWidth(), floatingTask.getHeight()),
false, null, onScreenRectF);
// Get the part of the floatingTask that intersects with the DragLayer (i.e. the
// on-screen portion)
onScreenRectF.intersect(
dragLayer.getLeft(),
dragLayer.getTop(),
dragLayer.getRight(),
dragLayer.getBottom()
);
setter.setFloat(
mRecentsView.getFirstFloatingTaskView(),
PRIMARY_TRANSLATE_OFFSCREEN,
mRecentsView.getPagedOrientationHandler()
.getFloatingTaskOffscreenTranslationTarget(
floatingTask,
onScreenRectF,
floatingTask.getStagePosition(),
mLauncher.getDeviceProfile()
),
config.getInterpolator(
ANIM_OVERVIEW_SPLIT_SELECT_FLOATING_TASK_TRANSLATE_OFFSCREEN,
LINEAR
));
setter.setViewAlpha(
mRecentsView.getSplitInstructionsView(),
0,
config.getInterpolator(
ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE,
LINEAR
)
);
}
setter.add(mRecentsView.getSplitSelectController().getSplitAnimationController()
.animateAwayPlaceholder(mLauncher));
setter.setViewAlpha(
mRecentsView.getSplitInstructionsView(),
0,
config.getInterpolator(
ANIM_OVERVIEW_SPLIT_SELECT_INSTRUCTIONS_FADE,
LINEAR
)
);
}
setter.setFloat(mRecentsView, getContentAlphaProperty(), toState.overviewUi ? 1 : 0,
@@ -193,6 +193,7 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;
@@ -406,7 +407,8 @@ public class QuickstepLauncher extends Launcher {
private List<SystemShortcut.Factory<QuickstepLauncher>> getSplitShortcuts() {
if (!ENABLE_SPLIT_FROM_WORKSPACE.get() || !mDeviceProfile.isTablet) {
if (!ENABLE_SPLIT_FROM_WORKSPACE.get() || !mDeviceProfile.isTablet ||
mSplitSelectStateController.isSplitSelectActive()) {
return Collections.emptyList();
}
RecentsView recentsView = getOverviewPanel();
@@ -545,11 +547,22 @@ public class QuickstepLauncher extends Launcher {
ArrayList<TouchController> list = new ArrayList<>();
list.add(getDragController());
Consumer<AnimatorSet> splitAnimator = animatorSet -> {
AnimatorSet anim = mSplitSelectStateController.getSplitAnimationController()
.animateAwayPlaceholder(QuickstepLauncher.this);
anim.addListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
mSplitSelectStateController.resetState();
}
});
animatorSet.play(anim);
};
switch (mode) {
case NO_BUTTON:
list.add(new NoButtonQuickSwitchTouchController(this));
list.add(new NavBarToHomeTouchController(this));
list.add(new NoButtonNavbarToOverviewTouchController(this));
list.add(new NavBarToHomeTouchController(this, splitAnimator));
list.add(new NoButtonNavbarToOverviewTouchController(this, splitAnimator));
break;
case TWO_BUTTONS:
list.add(new TwoButtonNavbarTouchController(this));
@@ -560,8 +573,8 @@ public class QuickstepLauncher extends Launcher {
break;
case THREE_BUTTONS:
list.add(new NoButtonQuickSwitchTouchController(this));
list.add(new NavBarToHomeTouchController(this));
list.add(new NoButtonNavbarToOverviewTouchController(this));
list.add(new NavBarToHomeTouchController(this, splitAnimator));
list.add(new NoButtonNavbarToOverviewTouchController(this, splitAnimator));
list.add(new PortraitStatesTouchController(this));
break;
default:
@@ -30,6 +30,7 @@ import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCH
import static com.android.launcher3.util.NavigationMode.THREE_BUTTONS;
import static com.android.systemui.shared.system.ActivityManagerWrapper.CLOSE_SYSTEM_WINDOWS_REASON_RECENTS;
import android.animation.AnimatorSet;
import android.animation.ValueAnimator;
import android.view.MotionEvent;
import android.view.animation.Interpolator;
@@ -43,6 +44,7 @@ import com.android.launcher3.allapps.AllAppsTransitionController;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.TouchController;
@@ -51,6 +53,8 @@ import com.android.quickstep.util.AnimatorControllerWithResistance;
import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.quickstep.views.RecentsView;
import java.util.function.Consumer;
/**
* Handles swiping up on the nav bar to go home from launcher, e.g. overview or all apps.
*/
@@ -62,6 +66,7 @@ public class NavBarToHomeTouchController implements TouchController,
private static final float OVERVIEW_TO_HOME_SCRIM_MULTIPLIER = 0.5f;
private final Launcher mLauncher;
private final Consumer<AnimatorSet> mCancelSplitRunnable;
private final SingleAxisSwipeDetector mSwipeDetector;
private final float mPullbackDistance;
@@ -70,8 +75,14 @@ public class NavBarToHomeTouchController implements TouchController,
private LauncherState mEndState = NORMAL;
private AnimatorPlaybackController mCurrentAnimation;
public NavBarToHomeTouchController(Launcher launcher) {
/**
* @param cancelSplitRunnable Called when split placeholder view needs to be cancelled.
* Animation should be added to the provided AnimatorSet
*/
public NavBarToHomeTouchController(Launcher launcher,
Consumer<AnimatorSet> cancelSplitRunnable) {
mLauncher = launcher;
mCancelSplitRunnable = cancelSplitRunnable;
mSwipeDetector = new SingleAxisSwipeDetector(mLauncher, this,
SingleAxisSwipeDetector.VERTICAL);
mPullbackDistance = mLauncher.getResources().getDimension(R.dimen.home_pullback_distance);
@@ -183,7 +194,10 @@ public class NavBarToHomeTouchController implements TouchController,
recentsView.switchToScreenshot(null,
() -> recentsView.finishRecentsAnimation(true /* toRecents */, null));
if (mStartState.overviewUi) {
new OverviewToHomeAnim(mLauncher, () -> onSwipeInteractionCompleted(mEndState))
new OverviewToHomeAnim(mLauncher, () -> onSwipeInteractionCompleted(mEndState),
FeatureFlags.ENABLE_SPLIT_FROM_WORKSPACE_TO_WORKSPACE.get()
? mCancelSplitRunnable
: null)
.animateWithVelocity(velocity);
} else {
mLauncher.getStateManager().goToState(mEndState, true,
@@ -31,6 +31,7 @@ import static com.android.launcher3.util.VibratorWrapper.OVERVIEW_HAPTIC;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_ONE_HANDED_ACTIVE;
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_OVERVIEW_DISABLED;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.ValueAnimator;
import android.graphics.PointF;
@@ -53,6 +54,8 @@ import com.android.quickstep.util.MotionPauseDetector;
import com.android.quickstep.util.OverviewToHomeAnim;
import com.android.quickstep.views.RecentsView;
import java.util.function.Consumer;
/**
* Touch controller which handles swipe and hold from the nav bar to go to Overview. Swiping above
* the nav bar falls back to go to All Apps. Swiping from the nav bar without holding goes to the
@@ -67,6 +70,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch
private static final float TRANSLATION_ANIM_VELOCITY_DP_PER_MS = 0.8f;
private final VibratorWrapper mVibratorWrapper;
private final Consumer<AnimatorSet> mCancelSplitRunnable;
private final RecentsView mRecentsView;
private final MotionPauseDetector mMotionPauseDetector;
private final float mMotionPauseMinDisplacement;
@@ -82,12 +86,18 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch
// Normal to Hint animation has flag SKIP_OVERVIEW, so we update this scrim with this animator.
private ObjectAnimator mNormalToHintOverviewScrimAnimator;
public NoButtonNavbarToOverviewTouchController(Launcher l) {
/**
* @param cancelSplitRunnable Called when split placeholder view needs to be cancelled.
* Animation should be added to the provided AnimatorSet
*/
public NoButtonNavbarToOverviewTouchController(Launcher l,
Consumer<AnimatorSet> cancelSplitRunnable) {
super(l);
mRecentsView = l.getOverviewPanel();
mMotionPauseDetector = new MotionPauseDetector(l);
mMotionPauseMinDisplacement = ViewConfiguration.get(l).getScaledTouchSlop();
mVibratorWrapper = VibratorWrapper.INSTANCE.get(l.getApplicationContext());
mCancelSplitRunnable = cancelSplitRunnable;
}
@Override
@@ -197,6 +207,9 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch
// state, but since the hint state tracks the entire screen without a clear endpoint, we
// need to manually set the duration to a reasonable value.
animator.setDuration(HINT_STATE.getTransitionDuration(mLauncher, true /* isToState */));
AnimatorSet animatorSet = new AnimatorSet();
mCancelSplitRunnable.accept(animatorSet);
animatorSet.start();
}
if (FeatureFlags.ENABLE_PREMIUM_HAPTICS_ALL_APPS.get() &&
((mFromState == NORMAL && mToState == ALL_APPS)
@@ -268,7 +281,7 @@ public class NoButtonNavbarToOverviewTouchController extends PortraitStatesTouch
private void goToOverviewOrHomeOnDragEnd(float velocity) {
boolean goToHomeInsteadOfOverview = !mMotionPauseDetector.isPaused();
if (goToHomeInsteadOfOverview) {
new OverviewToHomeAnim(mLauncher, () -> onSwipeInteractionCompleted(NORMAL))
new OverviewToHomeAnim(mLauncher, () -> onSwipeInteractionCompleted(NORMAL), null)
.animateWithVelocity(velocity);
}
if (mReachedOverview) {
@@ -58,6 +58,7 @@ import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatorPlaybackController;
import com.android.launcher3.anim.PendingAnimation;
import com.android.launcher3.compat.AccessibilityManagerCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.statemanager.StateManager.AtomicAnimationFactory;
@@ -117,6 +118,7 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
// animation callback
private final Handler mHandler = new Handler();
private final Runnable mAnimationStartTimeoutRunnable = this::onAnimationStartTimeout;
private SplitSelectStateController mSplitSelectStateController;
/**
* Init drag layer and overview panel views.
@@ -129,13 +131,12 @@ public final class RecentsActivity extends StatefulActivity<RecentsState> {
mFallbackRecentsView = findViewById(R.id.overview_panel);
mActionsView = findViewById(R.id.overview_actions_view);
getRootView().getSysUiScrim().getSysUIProgress().updateValue(0);
SplitSelectStateController controller =
mSplitSelectStateController =
new SplitSelectStateController(this, mHandler, getStateManager(),
null /* depthController */, getStatsLogManager(),
null /* depthController */, getStatsLogManager(),
SystemUiProxy.INSTANCE.get(this), RecentsModel.INSTANCE.get(this));
mDragLayer.recreateControllers();
mFallbackRecentsView.init(mActionsView, controller);
mFallbackRecentsView.init(mActionsView, mSplitSelectStateController);
mTISBindHelper = new TISBindHelper(this, this::onTISConnected);
}
@@ -22,12 +22,16 @@ import android.animation.Animator;
import android.animation.AnimatorSet;
import android.util.Log;
import androidx.annotation.Nullable;
import com.android.launcher3.Launcher;
import com.android.launcher3.LauncherState;
import com.android.launcher3.anim.AnimationSuccessListener;
import com.android.launcher3.statemanager.StateManager;
import com.android.launcher3.states.StateAnimationConfig;
import java.util.function.Consumer;
/**
* Runs an animation from overview to home. Currently, this animation is just a wrapper around the
* normal state transition and may play a {@link WorkspaceRevealAnim} if we're starting from an
@@ -39,14 +43,18 @@ public class OverviewToHomeAnim {
private final Launcher mLauncher;
private final Runnable mOnReachedHome;
@Nullable
private final Consumer<AnimatorSet> mSplitCancelConsumer;
// Only run mOnReachedHome when both of these are true.
private boolean mIsHomeStaggeredAnimFinished;
private boolean mIsOverviewHidden;
public OverviewToHomeAnim(Launcher launcher, Runnable onReachedHome) {
public OverviewToHomeAnim(Launcher launcher, Runnable onReachedHome,
@Nullable Consumer<AnimatorSet> splitCancelConsumer) {
mLauncher = launcher;
mOnReachedHome = onReachedHome;
mSplitCancelConsumer = splitCancelConsumer;
}
/**
@@ -92,6 +100,11 @@ public class OverviewToHomeAnim {
maybeOverviewToHomeAnimComplete();
}
});
if (mSplitCancelConsumer != null) {
// Clear split state when swiping to home
mSplitCancelConsumer.accept(anim);
}
anim.play(stateAnim);
stateManager.setCurrentAnimation(anim, NORMAL);
anim.start();
@@ -17,14 +17,22 @@
package com.android.quickstep.util
import android.animation.AnimatorSet
import android.animation.ObjectAnimator
import android.graphics.Bitmap
import android.graphics.Rect
import android.graphics.RectF
import android.graphics.drawable.Drawable
import android.view.View
import com.android.launcher3.DeviceProfile
import com.android.launcher3.Launcher
import com.android.launcher3.Utilities
import com.android.launcher3.anim.PendingAnimation
import com.android.launcher3.dragndrop.DragLayer
import com.android.launcher3.util.SplitConfigurationOptions.SplitSelectSource
import com.android.quickstep.views.FloatingTaskView
import com.android.quickstep.views.IconView
import com.android.quickstep.views.RecentsView
import com.android.quickstep.views.TaskThumbnailView
import com.android.quickstep.views.TaskView
import com.android.quickstep.views.TaskView.TaskIdAttributeContainer
@@ -176,4 +184,38 @@ class SplitAnimationController(val splitSelectStateController: SplitSelectStateC
TaskThumbnailView.SPLIT_SELECT_TRANSLATE_X, 0f))
}
}
fun animateAwayPlaceholder(mLauncher: Launcher) : AnimatorSet {
val animatorSet = AnimatorSet()
val recentsView : RecentsView<*, *> = mLauncher.getOverviewPanel()
val floatingTask: FloatingTaskView = splitSelectStateController.firstFloatingTaskView
?: return animatorSet
// We are in split selection state currently, transitioning to another state
val dragLayer: DragLayer = mLauncher.dragLayer
val onScreenRectF = RectF()
Utilities.getBoundsForViewInDragLayer(mLauncher.dragLayer, floatingTask,
Rect(0, 0, floatingTask.width, floatingTask.height),
false, null, onScreenRectF)
// Get the part of the floatingTask that intersects with the DragLayer (i.e. the
// on-screen portion)
onScreenRectF.intersect(
dragLayer.left.toFloat(),
dragLayer.top.toFloat(),
dragLayer.right.toFloat(),
dragLayer.bottom
.toFloat()
)
animatorSet.play(ObjectAnimator.ofFloat(floatingTask,
FloatingTaskView.PRIMARY_TRANSLATE_OFFSCREEN,
recentsView.pagedOrientationHandler
.getFloatingTaskOffscreenTranslationTarget(
floatingTask,
onScreenRectF,
floatingTask.stagePosition,
mLauncher.deviceProfile
)))
return animatorSet
}
}
@@ -895,6 +895,7 @@ public class SplitSelectStateController {
mFirstFloatingTaskView = floatingTaskView;
}
@Nullable
public FloatingTaskView getFirstFloatingTaskView() {
return mFirstFloatingTaskView;
}
@@ -6022,11 +6022,6 @@ public abstract class RecentsView<ACTIVITY_TYPE extends StatefulActivity<STATE_T
return mRecentsAnimationController;
}
@Nullable
public FloatingTaskView getFirstFloatingTaskView() {
return mSplitSelectStateController.getFirstFloatingTaskView();
}
@Nullable
public SplitInstructionsView getSplitInstructionsView() {
return mSplitInstructionsView;