Loading core/java/android/view/ImeBackAnimationController.java +14 −21 Original line number Diff line number Diff line Loading @@ -149,15 +149,17 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { private void setPreCommitProgress(float progress) { if (isHideAnimationInProgress()) return; setInterpolatedProgress(BACK_GESTURE.getInterpolation(progress) * PEEK_FRACTION); } private void setInterpolatedProgress(float progress) { if (mWindowInsetsAnimationController != null) { float hiddenY = mWindowInsetsAnimationController.getHiddenStateInsets().bottom; float shownY = mWindowInsetsAnimationController.getShownStateInsets().bottom; float imeHeight = shownY - hiddenY; float interpolatedProgress = BACK_GESTURE.getInterpolation(progress); int newY = (int) (imeHeight - interpolatedProgress * (imeHeight * PEEK_FRACTION)); int newY = (int) (imeHeight - progress * imeHeight); if (mStartRootScrollY != 0) { mViewRoot.setScrollY( (int) (mStartRootScrollY * (1 - interpolatedProgress * PEEK_FRACTION))); mViewRoot.setScrollY((int) (mStartRootScrollY * (1 - progress))); } mWindowInsetsAnimationController.setInsetsAndAlpha(Insets.of(0, 0, 0, newY), 1f, progress); Loading @@ -171,21 +173,14 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { return; } mTriggerBack = triggerBack; int currentBottomInset = mWindowInsetsAnimationController.getCurrentInsets().bottom; int targetBottomInset; if (triggerBack) { targetBottomInset = mWindowInsetsAnimationController.getHiddenStateInsets().bottom; } else { targetBottomInset = mWindowInsetsAnimationController.getShownStateInsets().bottom; } mPostCommitAnimator = ValueAnimator.ofFloat(currentBottomInset, targetBottomInset); float targetProgress = triggerBack ? 1f : 0f; mPostCommitAnimator = ValueAnimator.ofFloat( BACK_GESTURE.getInterpolation(mLastProgress) * PEEK_FRACTION, targetProgress); mPostCommitAnimator.setInterpolator( triggerBack ? STANDARD_ACCELERATE : EMPHASIZED_DECELERATE); mPostCommitAnimator.addUpdateListener(animation -> { int bottomInset = (int) ((float) animation.getAnimatedValue()); if (mWindowInsetsAnimationController != null) { mWindowInsetsAnimationController.setInsetsAndAlpha(Insets.of(0, 0, 0, bottomInset), 1f, animation.getAnimatedFraction()); setInterpolatedProgress((float) animation.getAnimatedValue()); } else { reset(); } Loading Loading @@ -213,14 +208,8 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { notifyHideIme(); // requesting IME as invisible during post-commit mInsetsController.setRequestedVisibleTypes(0, ime()); // Changes the animation state. This also notifies RootView of changed insets, which // causes it to reset its scrollY to 0f (animated) if it was panned mInsetsController.onAnimationStateChanged(ime(), /*running*/ true); } if (mStartRootScrollY != 0 && !triggerBack) { // This causes RootView to update its scroll back to the panned position mInsetsController.getHost().notifyInsetsChanged(); } } private void notifyHideIme() { Loading Loading @@ -282,6 +271,10 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { return mPostCommitAnimator != null && mTriggerBack; } boolean isAnimationInProgress() { return mIsPreCommitAnimationInProgress || mWindowInsetsAnimationController != null; } /** * Dump information about this ImeBackAnimationController * Loading core/java/android/view/ImeInsetsSourceConsumer.java +8 −1 Original line number Diff line number Diff line Loading @@ -70,7 +70,14 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { "ImeInsetsSourceConsumer#onAnimationFinished", mController.getHost().getInputMethodManager(), null /* icProto */); } boolean insetsChanged = super.onAnimationStateChanged(running); boolean insetsChanged = false; if (Flags.predictiveBackIme() && !running && isShowRequested() && mAnimationState == ANIMATION_STATE_HIDE) { // A user controlled hide animation may have ended in the shown state (e.g. // cancelled predictive back animation) -> Insets need to be reset to shown. insetsChanged |= applyLocalVisibilityOverride(); } insetsChanged |= super.onAnimationStateChanged(running); if (running && !isShowRequested() && mController.isPredictiveBackImeHideAnimInProgress()) { // IME predictive back animation switched from pre-commit to post-commit. Loading core/java/android/view/InsetsController.java +20 −13 Original line number Diff line number Diff line Loading @@ -1197,7 +1197,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation pendingRequest.listener, null /* frame */, true /* fromIme */, pendingRequest.mInsetsAnimationSpec, pendingRequest.animationType, pendingRequest.layoutInsetsDuringAnimation, pendingRequest.useInsetsAnimationThread, statsToken); pendingRequest.useInsetsAnimationThread, statsToken, false /* fromPredictiveBack */); } @Override Loading Loading @@ -1333,7 +1334,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // TODO(b/342111149): Create statsToken here once ImeTracker#onStart becomes async. controlAnimationUnchecked(types, cancellationSignal, listener, mFrame, fromIme, spec, animationType, getLayoutInsetsDuringAnimationMode(types, fromPredictiveBack), false /* useInsetsAnimationThread */, null); false /* useInsetsAnimationThread */, null, fromPredictiveBack); } private void controlAnimationUnchecked(@InsetsType int types, Loading @@ -1341,7 +1342,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation WindowInsetsAnimationControlListener listener, @Nullable Rect frame, boolean fromIme, InsetsAnimationSpec insetsAnimationSpec, @AnimationType int animationType, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation, boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken) { boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken, boolean fromPredictiveBack) { final boolean visible = layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN; // Basically, we accept the requested visibilities from the upstream callers... Loading @@ -1351,7 +1353,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // rejecting showing IME. controlAnimationUncheckedInner(types, cancellationSignal, listener, frame, fromIme, insetsAnimationSpec, animationType, layoutInsetsDuringAnimation, useInsetsAnimationThread, statsToken); useInsetsAnimationThread, statsToken, fromPredictiveBack); // We are finishing setting the requested visible types. Report them to the server // and/or the app. Loading @@ -1363,7 +1365,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation WindowInsetsAnimationControlListener listener, @Nullable Rect frame, boolean fromIme, InsetsAnimationSpec insetsAnimationSpec, @AnimationType int animationType, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation, boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken) { boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken, boolean fromPredictiveBack) { if ((types & mTypesBeingCancelled) != 0) { final boolean monitoredAnimation = animationType == ANIMATION_TYPE_SHOW || animationType == ANIMATION_TYPE_HIDE; Loading Loading @@ -1449,7 +1452,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } } else { Pair<Integer, Boolean> typesReadyPair = collectSourceControls( fromIme, types, controls, animationType, statsToken); fromIme, types, controls, animationType, statsToken, fromPredictiveBack); typesReady = typesReadyPair.first; boolean imeReady = typesReadyPair.second; if (DEBUG) { Loading Loading @@ -1585,7 +1588,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation */ private Pair<Integer, Boolean> collectSourceControls(boolean fromIme, @InsetsType int types, SparseArray<InsetsSourceControl> controls, @AnimationType int animationType, @Nullable ImeTracker.Token statsToken) { @Nullable ImeTracker.Token statsToken, boolean fromPredictiveBack) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_COLLECT_SOURCE_CONTROLS); Loading @@ -1597,7 +1600,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation continue; } boolean show = animationType == ANIMATION_TYPE_SHOW || animationType == ANIMATION_TYPE_USER; || (animationType == ANIMATION_TYPE_USER && (!fromPredictiveBack || !mHost.hasAnimationCallbacks())); boolean canRun = true; if (show) { // Show request Loading @@ -1620,7 +1624,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation break; } } else { consumer.requestHide(fromIme, statsToken); consumer.requestHide(fromIme || (fromPredictiveBack && mHost.hasAnimationCallbacks()), statsToken); } if (!canRun) { if (WARN) Log.w(TAG, String.format( Loading Loading @@ -1675,9 +1680,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private @LayoutInsetsDuringAnimation int getLayoutInsetsDuringAnimationMode( @InsetsType int types, boolean fromPredictiveBack) { if (fromPredictiveBack) { // When insets are animated by predictive back, we want insets to be shown to prevent a // jump cut from shown to hidden at the start of the predictive back animation if (fromPredictiveBack && !mHost.hasAnimationCallbacks()) { // When insets are animated by predictive back and the app does not have an animation // callback, we want insets to be shown to prevent a jump cut from shown to hidden at // the start of the predictive back animation return LAYOUT_INSETS_DURING_ANIMATION_SHOWN; } // Generally, we want to layout the opposite of the current state. This is to make animation Loading Loading @@ -2024,7 +2030,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation listener /* insetsAnimationSpec */, show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE, show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN, !hasAnimationCallbacks /* useInsetsAnimationThread */, statsToken); !hasAnimationCallbacks /* useInsetsAnimationThread */, statsToken, false /* fromPredictiveBack */); } /** Loading core/java/android/view/ViewRootImpl.java +6 −0 Original line number Diff line number Diff line Loading @@ -6094,6 +6094,12 @@ public final class ViewRootImpl implements ViewParent, } boolean scrollToRectOrFocus(Rect rectangle, boolean immediate) { if (mImeBackAnimationController.isAnimationInProgress()) { // IME predictive back animation is currently in progress which means that scrollY is // currently controlled by ImeBackAnimationController. return false; } final Rect ci = mAttachInfo.mContentInsets; final Rect vi = mAttachInfo.mVisibleInsets; int scrollY = 0; Loading core/tests/coretests/src/android/view/ImeBackAnimationControllerTest.java +10 −7 Original line number Diff line number Diff line Loading @@ -254,11 +254,8 @@ public class ImeBackAnimationControllerTest { float progress = 0.5f; mBackAnimationController.onBackProgressed(new BackEvent(100f, 0f, progress, EDGE_LEFT)); // verify correct ime insets manipulation float interpolatedProgress = BACK_GESTURE.getInterpolation(progress); int expectedInset = (int) (IME_HEIGHT - interpolatedProgress * PEEK_FRACTION * IME_HEIGHT); verify(mWindowInsetsAnimationController, times(1)).setInsetsAndAlpha( eq(Insets.of(0, 0, 0, expectedInset)), eq(1f), anyFloat()); eq(Insets.of(0, 0, 0, getImeHeight(progress))), eq(1f), anyFloat()); } @Test Loading @@ -268,12 +265,13 @@ public class ImeBackAnimationControllerTest { WindowInsetsAnimationControlListener animationControlListener = startBackGesture(); // progress back gesture mBackAnimationController.onBackProgressed(new BackEvent(100f, 0f, 0.5f, EDGE_LEFT)); float progress = 0.5f; mBackAnimationController.onBackProgressed(new BackEvent(100f, 0f, progress, EDGE_LEFT)); // commit back gesture mBackAnimationController.onBackInvoked(); // verify setInsetsAndAlpha never called due onReady delayed // verify setInsetsAndAlpha never called due to onReady delayed verify(mWindowInsetsAnimationController, never()).setInsetsAndAlpha(any(), anyInt(), anyFloat()); verify(mInsetsController, never()).setPredictiveBackImeHideAnimInProgress(eq(true)); Loading @@ -283,7 +281,7 @@ public class ImeBackAnimationControllerTest { // verify setInsetsAndAlpha immediately called verify(mWindowInsetsAnimationController, times(1)).setInsetsAndAlpha( eq(Insets.of(0, 0, 0, IME_HEIGHT)), eq(1f), anyFloat()); eq(Insets.of(0, 0, 0, getImeHeight(progress))), eq(1f), anyFloat()); // verify post-commit hide anim has started verify(mInsetsController, times(1)).setPredictiveBackImeHideAnimInProgress(eq(true)); }); Loading Loading @@ -319,4 +317,9 @@ public class ImeBackAnimationControllerTest { return animationControlListener.getValue(); } private int getImeHeight(float gestureProgress) { float interpolatedProgress = BACK_GESTURE.getInterpolation(gestureProgress); return (int) (IME_HEIGHT - interpolatedProgress * PEEK_FRACTION * IME_HEIGHT); } } Loading
core/java/android/view/ImeBackAnimationController.java +14 −21 Original line number Diff line number Diff line Loading @@ -149,15 +149,17 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { private void setPreCommitProgress(float progress) { if (isHideAnimationInProgress()) return; setInterpolatedProgress(BACK_GESTURE.getInterpolation(progress) * PEEK_FRACTION); } private void setInterpolatedProgress(float progress) { if (mWindowInsetsAnimationController != null) { float hiddenY = mWindowInsetsAnimationController.getHiddenStateInsets().bottom; float shownY = mWindowInsetsAnimationController.getShownStateInsets().bottom; float imeHeight = shownY - hiddenY; float interpolatedProgress = BACK_GESTURE.getInterpolation(progress); int newY = (int) (imeHeight - interpolatedProgress * (imeHeight * PEEK_FRACTION)); int newY = (int) (imeHeight - progress * imeHeight); if (mStartRootScrollY != 0) { mViewRoot.setScrollY( (int) (mStartRootScrollY * (1 - interpolatedProgress * PEEK_FRACTION))); mViewRoot.setScrollY((int) (mStartRootScrollY * (1 - progress))); } mWindowInsetsAnimationController.setInsetsAndAlpha(Insets.of(0, 0, 0, newY), 1f, progress); Loading @@ -171,21 +173,14 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { return; } mTriggerBack = triggerBack; int currentBottomInset = mWindowInsetsAnimationController.getCurrentInsets().bottom; int targetBottomInset; if (triggerBack) { targetBottomInset = mWindowInsetsAnimationController.getHiddenStateInsets().bottom; } else { targetBottomInset = mWindowInsetsAnimationController.getShownStateInsets().bottom; } mPostCommitAnimator = ValueAnimator.ofFloat(currentBottomInset, targetBottomInset); float targetProgress = triggerBack ? 1f : 0f; mPostCommitAnimator = ValueAnimator.ofFloat( BACK_GESTURE.getInterpolation(mLastProgress) * PEEK_FRACTION, targetProgress); mPostCommitAnimator.setInterpolator( triggerBack ? STANDARD_ACCELERATE : EMPHASIZED_DECELERATE); mPostCommitAnimator.addUpdateListener(animation -> { int bottomInset = (int) ((float) animation.getAnimatedValue()); if (mWindowInsetsAnimationController != null) { mWindowInsetsAnimationController.setInsetsAndAlpha(Insets.of(0, 0, 0, bottomInset), 1f, animation.getAnimatedFraction()); setInterpolatedProgress((float) animation.getAnimatedValue()); } else { reset(); } Loading Loading @@ -213,14 +208,8 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { notifyHideIme(); // requesting IME as invisible during post-commit mInsetsController.setRequestedVisibleTypes(0, ime()); // Changes the animation state. This also notifies RootView of changed insets, which // causes it to reset its scrollY to 0f (animated) if it was panned mInsetsController.onAnimationStateChanged(ime(), /*running*/ true); } if (mStartRootScrollY != 0 && !triggerBack) { // This causes RootView to update its scroll back to the panned position mInsetsController.getHost().notifyInsetsChanged(); } } private void notifyHideIme() { Loading Loading @@ -282,6 +271,10 @@ public class ImeBackAnimationController implements OnBackAnimationCallback { return mPostCommitAnimator != null && mTriggerBack; } boolean isAnimationInProgress() { return mIsPreCommitAnimationInProgress || mWindowInsetsAnimationController != null; } /** * Dump information about this ImeBackAnimationController * Loading
core/java/android/view/ImeInsetsSourceConsumer.java +8 −1 Original line number Diff line number Diff line Loading @@ -70,7 +70,14 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer { "ImeInsetsSourceConsumer#onAnimationFinished", mController.getHost().getInputMethodManager(), null /* icProto */); } boolean insetsChanged = super.onAnimationStateChanged(running); boolean insetsChanged = false; if (Flags.predictiveBackIme() && !running && isShowRequested() && mAnimationState == ANIMATION_STATE_HIDE) { // A user controlled hide animation may have ended in the shown state (e.g. // cancelled predictive back animation) -> Insets need to be reset to shown. insetsChanged |= applyLocalVisibilityOverride(); } insetsChanged |= super.onAnimationStateChanged(running); if (running && !isShowRequested() && mController.isPredictiveBackImeHideAnimInProgress()) { // IME predictive back animation switched from pre-commit to post-commit. Loading
core/java/android/view/InsetsController.java +20 −13 Original line number Diff line number Diff line Loading @@ -1197,7 +1197,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation pendingRequest.listener, null /* frame */, true /* fromIme */, pendingRequest.mInsetsAnimationSpec, pendingRequest.animationType, pendingRequest.layoutInsetsDuringAnimation, pendingRequest.useInsetsAnimationThread, statsToken); pendingRequest.useInsetsAnimationThread, statsToken, false /* fromPredictiveBack */); } @Override Loading Loading @@ -1333,7 +1334,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // TODO(b/342111149): Create statsToken here once ImeTracker#onStart becomes async. controlAnimationUnchecked(types, cancellationSignal, listener, mFrame, fromIme, spec, animationType, getLayoutInsetsDuringAnimationMode(types, fromPredictiveBack), false /* useInsetsAnimationThread */, null); false /* useInsetsAnimationThread */, null, fromPredictiveBack); } private void controlAnimationUnchecked(@InsetsType int types, Loading @@ -1341,7 +1342,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation WindowInsetsAnimationControlListener listener, @Nullable Rect frame, boolean fromIme, InsetsAnimationSpec insetsAnimationSpec, @AnimationType int animationType, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation, boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken) { boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken, boolean fromPredictiveBack) { final boolean visible = layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN; // Basically, we accept the requested visibilities from the upstream callers... Loading @@ -1351,7 +1353,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation // rejecting showing IME. controlAnimationUncheckedInner(types, cancellationSignal, listener, frame, fromIme, insetsAnimationSpec, animationType, layoutInsetsDuringAnimation, useInsetsAnimationThread, statsToken); useInsetsAnimationThread, statsToken, fromPredictiveBack); // We are finishing setting the requested visible types. Report them to the server // and/or the app. Loading @@ -1363,7 +1365,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation WindowInsetsAnimationControlListener listener, @Nullable Rect frame, boolean fromIme, InsetsAnimationSpec insetsAnimationSpec, @AnimationType int animationType, @LayoutInsetsDuringAnimation int layoutInsetsDuringAnimation, boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken) { boolean useInsetsAnimationThread, @Nullable ImeTracker.Token statsToken, boolean fromPredictiveBack) { if ((types & mTypesBeingCancelled) != 0) { final boolean monitoredAnimation = animationType == ANIMATION_TYPE_SHOW || animationType == ANIMATION_TYPE_HIDE; Loading Loading @@ -1449,7 +1452,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation } } else { Pair<Integer, Boolean> typesReadyPair = collectSourceControls( fromIme, types, controls, animationType, statsToken); fromIme, types, controls, animationType, statsToken, fromPredictiveBack); typesReady = typesReadyPair.first; boolean imeReady = typesReadyPair.second; if (DEBUG) { Loading Loading @@ -1585,7 +1588,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation */ private Pair<Integer, Boolean> collectSourceControls(boolean fromIme, @InsetsType int types, SparseArray<InsetsSourceControl> controls, @AnimationType int animationType, @Nullable ImeTracker.Token statsToken) { @Nullable ImeTracker.Token statsToken, boolean fromPredictiveBack) { ImeTracker.forLogging().onProgress(statsToken, ImeTracker.PHASE_CLIENT_COLLECT_SOURCE_CONTROLS); Loading @@ -1597,7 +1600,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation continue; } boolean show = animationType == ANIMATION_TYPE_SHOW || animationType == ANIMATION_TYPE_USER; || (animationType == ANIMATION_TYPE_USER && (!fromPredictiveBack || !mHost.hasAnimationCallbacks())); boolean canRun = true; if (show) { // Show request Loading @@ -1620,7 +1624,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation break; } } else { consumer.requestHide(fromIme, statsToken); consumer.requestHide(fromIme || (fromPredictiveBack && mHost.hasAnimationCallbacks()), statsToken); } if (!canRun) { if (WARN) Log.w(TAG, String.format( Loading Loading @@ -1675,9 +1680,10 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation private @LayoutInsetsDuringAnimation int getLayoutInsetsDuringAnimationMode( @InsetsType int types, boolean fromPredictiveBack) { if (fromPredictiveBack) { // When insets are animated by predictive back, we want insets to be shown to prevent a // jump cut from shown to hidden at the start of the predictive back animation if (fromPredictiveBack && !mHost.hasAnimationCallbacks()) { // When insets are animated by predictive back and the app does not have an animation // callback, we want insets to be shown to prevent a jump cut from shown to hidden at // the start of the predictive back animation return LAYOUT_INSETS_DURING_ANIMATION_SHOWN; } // Generally, we want to layout the opposite of the current state. This is to make animation Loading Loading @@ -2024,7 +2030,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation listener /* insetsAnimationSpec */, show ? ANIMATION_TYPE_SHOW : ANIMATION_TYPE_HIDE, show ? LAYOUT_INSETS_DURING_ANIMATION_SHOWN : LAYOUT_INSETS_DURING_ANIMATION_HIDDEN, !hasAnimationCallbacks /* useInsetsAnimationThread */, statsToken); !hasAnimationCallbacks /* useInsetsAnimationThread */, statsToken, false /* fromPredictiveBack */); } /** Loading
core/java/android/view/ViewRootImpl.java +6 −0 Original line number Diff line number Diff line Loading @@ -6094,6 +6094,12 @@ public final class ViewRootImpl implements ViewParent, } boolean scrollToRectOrFocus(Rect rectangle, boolean immediate) { if (mImeBackAnimationController.isAnimationInProgress()) { // IME predictive back animation is currently in progress which means that scrollY is // currently controlled by ImeBackAnimationController. return false; } final Rect ci = mAttachInfo.mContentInsets; final Rect vi = mAttachInfo.mVisibleInsets; int scrollY = 0; Loading
core/tests/coretests/src/android/view/ImeBackAnimationControllerTest.java +10 −7 Original line number Diff line number Diff line Loading @@ -254,11 +254,8 @@ public class ImeBackAnimationControllerTest { float progress = 0.5f; mBackAnimationController.onBackProgressed(new BackEvent(100f, 0f, progress, EDGE_LEFT)); // verify correct ime insets manipulation float interpolatedProgress = BACK_GESTURE.getInterpolation(progress); int expectedInset = (int) (IME_HEIGHT - interpolatedProgress * PEEK_FRACTION * IME_HEIGHT); verify(mWindowInsetsAnimationController, times(1)).setInsetsAndAlpha( eq(Insets.of(0, 0, 0, expectedInset)), eq(1f), anyFloat()); eq(Insets.of(0, 0, 0, getImeHeight(progress))), eq(1f), anyFloat()); } @Test Loading @@ -268,12 +265,13 @@ public class ImeBackAnimationControllerTest { WindowInsetsAnimationControlListener animationControlListener = startBackGesture(); // progress back gesture mBackAnimationController.onBackProgressed(new BackEvent(100f, 0f, 0.5f, EDGE_LEFT)); float progress = 0.5f; mBackAnimationController.onBackProgressed(new BackEvent(100f, 0f, progress, EDGE_LEFT)); // commit back gesture mBackAnimationController.onBackInvoked(); // verify setInsetsAndAlpha never called due onReady delayed // verify setInsetsAndAlpha never called due to onReady delayed verify(mWindowInsetsAnimationController, never()).setInsetsAndAlpha(any(), anyInt(), anyFloat()); verify(mInsetsController, never()).setPredictiveBackImeHideAnimInProgress(eq(true)); Loading @@ -283,7 +281,7 @@ public class ImeBackAnimationControllerTest { // verify setInsetsAndAlpha immediately called verify(mWindowInsetsAnimationController, times(1)).setInsetsAndAlpha( eq(Insets.of(0, 0, 0, IME_HEIGHT)), eq(1f), anyFloat()); eq(Insets.of(0, 0, 0, getImeHeight(progress))), eq(1f), anyFloat()); // verify post-commit hide anim has started verify(mInsetsController, times(1)).setPredictiveBackImeHideAnimInProgress(eq(true)); }); Loading Loading @@ -319,4 +317,9 @@ public class ImeBackAnimationControllerTest { return animationControlListener.getValue(); } private int getImeHeight(float gestureProgress) { float interpolatedProgress = BACK_GESTURE.getInterpolation(gestureProgress); return (int) (IME_HEIGHT - interpolatedProgress * PEEK_FRACTION * IME_HEIGHT); } }