Loading core/java/android/view/ImeBackAnimationController.java +22 −0 Original line number Diff line number Diff line Loading @@ -31,9 +31,12 @@ import android.util.Log; import android.view.animation.BackGestureInterpolator; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import android.view.inputmethod.ImeTracker; import android.window.BackEvent; import android.window.OnBackAnimationCallback; import com.android.internal.inputmethod.SoftInputShowHideReason; /** * Controller for IME predictive back animation * Loading Loading @@ -192,6 +195,24 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { mPostCommitAnimator.setDuration( triggerBack ? POST_COMMIT_DURATION_MS : POST_COMMIT_CANCEL_DURATION_MS); mPostCommitAnimator.start(); if (triggerBack) { mInsetsController.setPredictiveBackImeHideAnimInProgress(true); notifyHideIme(); } } private void notifyHideIme() { ImeTracker.Token statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.HIDE_SOFT_INPUT_REQUEST_HIDE_WITH_CONTROL, true); // This notifies the IME that it is being hidden. In response, the IME will unregister the // animation callback, such that new back gestures happening during the post-commit phase of // the hide animation can already dispatch to a new callback. // Note that the IME will call hide() in InsetsController. InsetsController will not animate // that hide request if it sees that ImeBackAnimationController is already animating // the IME away mInsetsController.getHost().getInputMethodManager() .notifyImeHidden(mInsetsController.getHost().getWindowToken(), statsToken); } private void reset() { Loading @@ -200,6 +221,7 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { mLastProgress = 0f; mTriggerBack = false; mIsPreCommitAnimationInProgress = false; mInsetsController.setPredictiveBackImeHideAnimInProgress(false); } private void resetPostCommitAnimator() { Loading core/java/android/view/ImeInsetsSourceConsumer.java +2 −1 Original line number Diff line number Diff line Loading @@ -243,7 +243,8 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { * {@link InputMethodManager#showSoftInput(View, int)} is called. */ public void onShowRequested() { if (mAnimationState == ANIMATION_STATE_HIDE) { if (mAnimationState == ANIMATION_STATE_HIDE || mController.isPredictiveBackImeHideAnimInProgress()) { mHasPendingRequest = true; } } Loading core/java/android/view/InsetsController.java +13 −2 Original line number Diff line number Diff line Loading @@ -651,6 +651,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private @Appearance int mAppearanceControlled; private @Appearance int mAppearanceFromResource; private boolean mBehaviorControlled; private boolean mIsPredictiveBackImeHideAnimInProgress; private final Runnable mPendingControlTimeout = this::abortPendingImeControlRequest; private final ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners Loading Loading @@ -1027,6 +1028,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation reportRequestedVisibleTypes(); } void setPredictiveBackImeHideAnimInProgress(boolean isInProgress) { mIsPredictiveBackImeHideAnimInProgress = isInProgress; } boolean isPredictiveBackImeHideAnimInProgress() { return mIsPredictiveBackImeHideAnimInProgress; } @Override public void show(@InsetsType int types) { show(types, false /* fromIme */, null /* statsToken */); Loading Loading @@ -1090,7 +1099,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } continue; } if (fromIme && animationType == ANIMATION_TYPE_USER) { if (fromIme && animationType == ANIMATION_TYPE_USER && !mIsPredictiveBackImeHideAnimInProgress) { // App is already controlling the IME, don't cancel it. if (isIme) { ImeTracker.forLogging().onFailed( Loading Loading @@ -1186,7 +1196,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } } if (!requestedVisible && animationType == ANIMATION_TYPE_NONE || animationType == ANIMATION_TYPE_HIDE) { || animationType == ANIMATION_TYPE_HIDE || (animationType == ANIMATION_TYPE_USER && mIsPredictiveBackImeHideAnimInProgress)) { // no-op: already hidden or animating out (because window visibility is // applied before starting animation). if (isImeAnimation) { Loading Loading
core/java/android/view/ImeBackAnimationController.java +22 −0 Original line number Diff line number Diff line Loading @@ -31,9 +31,12 @@ import android.util.Log; import android.view.animation.BackGestureInterpolator; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; import android.view.inputmethod.ImeTracker; import android.window.BackEvent; import android.window.OnBackAnimationCallback; import com.android.internal.inputmethod.SoftInputShowHideReason; /** * Controller for IME predictive back animation * Loading Loading @@ -192,6 +195,24 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { mPostCommitAnimator.setDuration( triggerBack ? POST_COMMIT_DURATION_MS : POST_COMMIT_CANCEL_DURATION_MS); mPostCommitAnimator.start(); if (triggerBack) { mInsetsController.setPredictiveBackImeHideAnimInProgress(true); notifyHideIme(); } } private void notifyHideIme() { ImeTracker.Token statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE, ImeTracker.ORIGIN_CLIENT, SoftInputShowHideReason.HIDE_SOFT_INPUT_REQUEST_HIDE_WITH_CONTROL, true); // This notifies the IME that it is being hidden. In response, the IME will unregister the // animation callback, such that new back gestures happening during the post-commit phase of // the hide animation can already dispatch to a new callback. // Note that the IME will call hide() in InsetsController. InsetsController will not animate // that hide request if it sees that ImeBackAnimationController is already animating // the IME away mInsetsController.getHost().getInputMethodManager() .notifyImeHidden(mInsetsController.getHost().getWindowToken(), statsToken); } private void reset() { Loading @@ -200,6 +221,7 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { mLastProgress = 0f; mTriggerBack = false; mIsPreCommitAnimationInProgress = false; mInsetsController.setPredictiveBackImeHideAnimInProgress(false); } private void resetPostCommitAnimator() { Loading
core/java/android/view/ImeInsetsSourceConsumer.java +2 −1 Original line number Diff line number Diff line Loading @@ -243,7 +243,8 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { * {@link InputMethodManager#showSoftInput(View, int)} is called. */ public void onShowRequested() { if (mAnimationState == ANIMATION_STATE_HIDE) { if (mAnimationState == ANIMATION_STATE_HIDE || mController.isPredictiveBackImeHideAnimInProgress()) { mHasPendingRequest = true; } } Loading
core/java/android/view/InsetsController.java +13 −2 Original line number Diff line number Diff line Loading @@ -651,6 +651,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private @Appearance int mAppearanceControlled; private @Appearance int mAppearanceFromResource; private boolean mBehaviorControlled; private boolean mIsPredictiveBackImeHideAnimInProgress; private final Runnable mPendingControlTimeout = this::abortPendingImeControlRequest; private final ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners Loading Loading @@ -1027,6 +1028,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation reportRequestedVisibleTypes(); } void setPredictiveBackImeHideAnimInProgress(boolean isInProgress) { mIsPredictiveBackImeHideAnimInProgress = isInProgress; } boolean isPredictiveBackImeHideAnimInProgress() { return mIsPredictiveBackImeHideAnimInProgress; } @Override public void show(@InsetsType int types) { show(types, false /* fromIme */, null /* statsToken */); Loading Loading @@ -1090,7 +1099,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } continue; } if (fromIme && animationType == ANIMATION_TYPE_USER) { if (fromIme && animationType == ANIMATION_TYPE_USER && !mIsPredictiveBackImeHideAnimInProgress) { // App is already controlling the IME, don't cancel it. if (isIme) { ImeTracker.forLogging().onFailed( Loading Loading @@ -1186,7 +1196,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } } if (!requestedVisible && animationType == ANIMATION_TYPE_NONE || animationType == ANIMATION_TYPE_HIDE) { || animationType == ANIMATION_TYPE_HIDE || (animationType == ANIMATION_TYPE_USER && mIsPredictiveBackImeHideAnimInProgress)) { // no-op: already hidden or animating out (because window visibility is // applied before starting animation). if (isImeAnimation) { Loading