mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-03-04 18:06:48 +00:00
Stash taskbar when IME is present, including during gestures
- SysUI removes SYSUI_STATE_IME_SHOWING when starting a gesture from an app, but because unstashing has implications on the gesture transition (e.g. clips the bottom of the app), we defer handling the ime hiding until the gesture settles. Repurposed the flow that swaps the taskbar background during the gesture to support this case as well. - Delay the unstash when IME is closing, to align with the end of the IME exit transition - Remove TaskbarViewController.ALPHA_INDEX_IME now that we stash when IME is opening, since stashing already hides the taskbar icons - Also support passing a starting progress to the stashed handle reveal animation, to allow it to be reversed when cancelled. For example, when returning to an app that has IME showing, we first start unstashing because we're in an app, but then we get the signal that IME is attached so we stash again almost immediately (within a frame or two). Test: In both 3 button and fully gestural, open a keyboard in an app, ensure taskbar gets out of the way and then reappears at the end when the keyboard is dismissed Bug: 202511986 Change-Id: I93c298a98ba369ea6310466ff3f802231c582687
This commit is contained in:
@@ -19,6 +19,7 @@ import static android.view.HapticFeedbackConstants.LONG_PRESS;
|
||||
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_HIDE;
|
||||
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_LONGPRESS_SHOW;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_IME_SHOWING;
|
||||
import static com.android.systemui.shared.system.QuickStepContract.SYSUI_STATE_SCREEN_PINNING;
|
||||
|
||||
import android.animation.Animator;
|
||||
@@ -48,17 +49,24 @@ public class TaskbarStashController {
|
||||
public static final int FLAG_STASHED_IN_APP_PINNED = 1 << 2; // app pinning
|
||||
public static final int FLAG_STASHED_IN_APP_EMPTY = 1 << 3; // no hotseat icons
|
||||
public static final int FLAG_STASHED_IN_APP_SETUP = 1 << 4; // setup wizard and AllSetActivity
|
||||
public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 5;
|
||||
public static final int FLAG_STASHED_IN_APP_IME = 1 << 5; // IME is visible
|
||||
public static final int FLAG_IN_STASHED_LAUNCHER_STATE = 1 << 6;
|
||||
|
||||
// If we're in an app and any of these flags are enabled, taskbar should be stashed.
|
||||
public static final int FLAGS_STASHED_IN_APP = FLAG_STASHED_IN_APP_MANUAL
|
||||
| FLAG_STASHED_IN_APP_PINNED | FLAG_STASHED_IN_APP_EMPTY | FLAG_STASHED_IN_APP_SETUP;
|
||||
| FLAG_STASHED_IN_APP_PINNED | FLAG_STASHED_IN_APP_EMPTY | FLAG_STASHED_IN_APP_SETUP
|
||||
| FLAG_STASHED_IN_APP_IME;
|
||||
|
||||
/**
|
||||
* How long to stash/unstash when manually invoked via long press.
|
||||
*/
|
||||
public static final long TASKBAR_STASH_DURATION = 300;
|
||||
|
||||
/**
|
||||
* How long to stash/unstash when keyboard is appearing/disappearing.
|
||||
*/
|
||||
private static final long TASKBAR_STASH_DURATION_FOR_IME = 80;
|
||||
|
||||
/**
|
||||
* The scale TaskbarView animates to when being stashed.
|
||||
*/
|
||||
@@ -100,6 +108,7 @@ public class TaskbarStashController {
|
||||
private TaskbarControllers mControllers;
|
||||
// Taskbar background properties.
|
||||
private AnimatedFloat mTaskbarBackgroundOffset;
|
||||
private AnimatedFloat mTaskbarImeBgAlpha;
|
||||
// TaskbarView icon properties.
|
||||
private AlphaProperty mIconAlphaForStash;
|
||||
private AnimatedFloat mIconScaleForStash;
|
||||
@@ -113,6 +122,8 @@ public class TaskbarStashController {
|
||||
private int mState;
|
||||
|
||||
private @Nullable AnimatorSet mAnimator;
|
||||
private boolean mIsSystemGestureInProgress;
|
||||
private boolean mIsImeShowing;
|
||||
|
||||
// Evaluate whether the handle should be stashed
|
||||
private final StatePropertyHolder mStatePropertyHolder = new StatePropertyHolder(
|
||||
@@ -137,6 +148,7 @@ public class TaskbarStashController {
|
||||
|
||||
TaskbarDragLayerController dragLayerController = controllers.taskbarDragLayerController;
|
||||
mTaskbarBackgroundOffset = dragLayerController.getTaskbarBackgroundOffset();
|
||||
mTaskbarImeBgAlpha = dragLayerController.getImeBgTaskbar();
|
||||
|
||||
TaskbarViewController taskbarViewController = controllers.taskbarViewController;
|
||||
mIconAlphaForStash = taskbarViewController.getTaskbarIconAlpha().getProperty(
|
||||
@@ -271,17 +283,21 @@ public class TaskbarStashController {
|
||||
* Create a stash animation and save to {@link #mAnimator}.
|
||||
* @param isStashed whether it's a stash animation or an unstash animation
|
||||
* @param duration duration of the animation
|
||||
* @param startDelay how many milliseconds to delay the animation after starting it.
|
||||
*/
|
||||
private void createAnimToIsStashed(boolean isStashed, long duration) {
|
||||
private void createAnimToIsStashed(boolean isStashed, long duration, long startDelay) {
|
||||
if (mAnimator != null) {
|
||||
mAnimator.cancel();
|
||||
}
|
||||
mAnimator = new AnimatorSet();
|
||||
|
||||
if (!supportsVisualStashing()) {
|
||||
// Just hide/show the icons instead of stashing into a handle.
|
||||
// Just hide/show the icons and background instead of stashing into a handle.
|
||||
mAnimator.play(mIconAlphaForStash.animateToValue(isStashed ? 0 : 1)
|
||||
.setDuration(duration));
|
||||
mAnimator.play(mTaskbarImeBgAlpha.animateToValue(
|
||||
hasAnyFlag(FLAG_STASHED_IN_APP_IME) ? 0 : 1).setDuration(duration));
|
||||
mAnimator.setStartDelay(startDelay);
|
||||
mAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
@@ -332,11 +348,8 @@ public class TaskbarStashController {
|
||||
);
|
||||
}
|
||||
|
||||
Animator stashedHandleRevealAnim = mControllers.stashedHandleViewController
|
||||
.createRevealAnimToIsStashed(isStashed);
|
||||
if (stashedHandleRevealAnim != null) {
|
||||
fullLengthAnimatorSet.play(stashedHandleRevealAnim);
|
||||
}
|
||||
fullLengthAnimatorSet.play(mControllers.stashedHandleViewController
|
||||
.createRevealAnimToIsStashed(isStashed));
|
||||
// Return the stashed handle to its default scale in case it was changed as part of the
|
||||
// feedforward hint. Note that the reveal animation above also visually scales it.
|
||||
fullLengthAnimatorSet.play(mTaskbarStashedHandleHintScale.animateToValue(1f));
|
||||
@@ -348,6 +361,7 @@ public class TaskbarStashController {
|
||||
|
||||
mAnimator.playTogether(fullLengthAnimatorSet, firstHalfAnimatorSet,
|
||||
secondHalfAnimatorSet);
|
||||
mAnimator.setStartDelay(startDelay);
|
||||
mAnimator.addListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationStart(Animator animation) {
|
||||
@@ -406,6 +420,10 @@ public class TaskbarStashController {
|
||||
mStatePropertyHolder.setState(mState, duration, true);
|
||||
}
|
||||
|
||||
public void applyState(long duration, long startDelay) {
|
||||
mStatePropertyHolder.setState(mState, duration, startDelay, true);
|
||||
}
|
||||
|
||||
public Animator applyStateWithoutStart() {
|
||||
return applyStateWithoutStart(TASKBAR_STASH_DURATION);
|
||||
}
|
||||
@@ -414,11 +432,50 @@ public class TaskbarStashController {
|
||||
return mStatePropertyHolder.setState(mState, duration, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Should be called when a system gesture starts and settles, so we can defer updating
|
||||
* FLAG_STASHED_IN_APP_IME until after the gesture transition completes.
|
||||
*/
|
||||
public void setSystemGestureInProgress(boolean inProgress) {
|
||||
mIsSystemGestureInProgress = inProgress;
|
||||
// Only update FLAG_STASHED_IN_APP_IME when system gesture is not in progress.
|
||||
if (!mIsSystemGestureInProgress) {
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_IME, mIsImeShowing);
|
||||
applyState(TASKBAR_STASH_DURATION_FOR_IME, getTaskbarStashStartDelayForIme());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When hiding the IME, delay the unstash animation to align with the end of the transition.
|
||||
*/
|
||||
private long getTaskbarStashStartDelayForIme() {
|
||||
if (mIsImeShowing) {
|
||||
// Only delay when IME is exiting, not entering.
|
||||
return 0;
|
||||
}
|
||||
// This duration is based on input_method_extract_exit.xml.
|
||||
long imeExitDuration = mControllers.taskbarActivityContext.getResources()
|
||||
.getInteger(android.R.integer.config_shortAnimTime);
|
||||
return imeExitDuration - TASKBAR_STASH_DURATION_FOR_IME;
|
||||
}
|
||||
|
||||
/** Called when some system ui state has changed. (See SYSUI_STATE_... in QuickstepContract) */
|
||||
public void updateStateForSysuiFlags(int systemUiStateFlags, boolean skipAnim) {
|
||||
long animDuration = TASKBAR_STASH_DURATION;
|
||||
long startDelay = 0;
|
||||
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_PINNED,
|
||||
hasAnyFlag(systemUiStateFlags, SYSUI_STATE_SCREEN_PINNING));
|
||||
applyState(skipAnim ? 0 : TASKBAR_STASH_DURATION);
|
||||
|
||||
// Only update FLAG_STASHED_IN_APP_IME when system gesture is not in progress.
|
||||
mIsImeShowing = hasAnyFlag(systemUiStateFlags, SYSUI_STATE_IME_SHOWING);
|
||||
if (!mIsSystemGestureInProgress) {
|
||||
updateStateForFlag(FLAG_STASHED_IN_APP_IME, mIsImeShowing);
|
||||
animDuration = TASKBAR_STASH_DURATION_FOR_IME;
|
||||
startDelay = getTaskbarStashStartDelayForIme();
|
||||
}
|
||||
|
||||
applyState(skipAnim ? 0 : animDuration, skipAnim ? 0 : startDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -474,16 +531,34 @@ public class TaskbarStashController {
|
||||
mStashCondition = stashCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see #setState(int, long, long, boolean) with a default startDelay = 0.
|
||||
*/
|
||||
public Animator setState(int flags, long duration, boolean start) {
|
||||
return setState(flags, duration, 0 /* startDelay */, start);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the latest state, potentially calling onStateChangeApplied() and creating a new
|
||||
* animation (stored in mAnimator) which is started if {@param start} is true.
|
||||
* @param flags The latest flags to apply (see the top of this file).
|
||||
* @param duration The length of the animation.
|
||||
* @param startDelay How long to delay the animation after calling start().
|
||||
* @param start Whether to start mAnimator immediately.
|
||||
* @return mAnimator if mIsStashed changed, else null.
|
||||
*/
|
||||
public Animator setState(int flags, long duration, long startDelay, boolean start) {
|
||||
int changedFlags = mPrevFlags ^ flags;
|
||||
if (mPrevFlags != flags) {
|
||||
int changedFlags = mPrevFlags ^ flags;
|
||||
onStateChangeApplied(changedFlags);
|
||||
mPrevFlags = flags;
|
||||
}
|
||||
boolean isStashed = mStashCondition.test(flags);
|
||||
if (mIsStashed != isStashed) {
|
||||
mIsStashed = isStashed;
|
||||
createAnimToIsStashed(mIsStashed, duration);
|
||||
|
||||
// This sets mAnimator.
|
||||
createAnimToIsStashed(mIsStashed, duration, startDelay);
|
||||
if (start) {
|
||||
mAnimator.start();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user