Merge "Animate IME with zero insets" into rvc-dev am: cc498f3e69 am: 5208fccc52

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11829827

Change-Id: I8fe5b84f272a6ddfe95c129440ed0390b7ce15c3
This commit is contained in:
TreeHugger Robot
2020-06-20 17:30:06 +00:00
committed by Automerger Merge Worker
6 changed files with 65 additions and 14 deletions

View File

@@ -16,13 +16,14 @@
package android.view; package android.view;
import static android.view.InsetsController.ANIMATION_TYPE_SHOW;
import static android.view.InsetsController.AnimationType; import static android.view.InsetsController.AnimationType;
import static android.view.InsetsController.DEBUG; import static android.view.InsetsController.DEBUG;
import static android.view.InsetsState.ISIDE_BOTTOM; import static android.view.InsetsState.ISIDE_BOTTOM;
import static android.view.InsetsState.ISIDE_FLOATING;
import static android.view.InsetsState.ISIDE_LEFT; import static android.view.InsetsState.ISIDE_LEFT;
import static android.view.InsetsState.ISIDE_RIGHT; import static android.view.InsetsState.ISIDE_RIGHT;
import static android.view.InsetsState.ISIDE_TOP; import static android.view.InsetsState.ISIDE_TOP;
import static android.view.InsetsState.ITYPE_IME;
import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE; import static com.android.internal.annotations.VisibleForTesting.Visibility.PACKAGE;
@@ -74,6 +75,8 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
private final @InsetsType int mTypes; private final @InsetsType int mTypes;
private final InsetsAnimationControlCallbacks mController; private final InsetsAnimationControlCallbacks mController;
private final WindowInsetsAnimation mAnimation; private final WindowInsetsAnimation mAnimation;
/** @see WindowInsetsAnimationController#hasZeroInsetsIme */
private final boolean mHasZeroInsetsIme;
private Insets mCurrentInsets; private Insets mCurrentInsets;
private Insets mPendingInsets; private Insets mPendingInsets;
private float mPendingFraction; private float mPendingFraction;
@@ -102,6 +105,12 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
null /* typeSideMap */); null /* typeSideMap */);
mShownInsets = calculateInsets(mInitialInsetsState, frame, controls, true /* shown */, mShownInsets = calculateInsets(mInitialInsetsState, frame, controls, true /* shown */,
mTypeSideMap); mTypeSideMap);
mHasZeroInsetsIme = mShownInsets.bottom == 0 && controlsInternalType(ITYPE_IME);
if (mHasZeroInsetsIme) {
// IME has shownInsets of ZERO, and can't map to a side by default.
// Map zero insets IME to bottom, making it a special case of bottom insets.
mTypeSideMap.put(ITYPE_IME, ISIDE_BOTTOM);
}
buildTypeSourcesMap(mTypeSideMap, mSideSourceMap, mControls); buildTypeSourcesMap(mTypeSideMap, mSideSourceMap, mControls);
mAnimation = new WindowInsetsAnimation(mTypes, interpolator, mAnimation = new WindowInsetsAnimation(mTypes, interpolator,
@@ -112,6 +121,11 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
new Bounds(mHiddenInsets, mShownInsets)); new Bounds(mHiddenInsets, mShownInsets));
} }
@Override
public boolean hasZeroInsetsIme() {
return mHasZeroInsetsIme;
}
@Override @Override
public Insets getHiddenStateInsets() { public Insets getHiddenStateInsets() {
return mHiddenInsets; return mHiddenInsets;
@@ -182,8 +196,6 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
params, state, mPendingAlpha); params, state, mPendingAlpha);
updateLeashesForSide(ISIDE_BOTTOM, offset.bottom, mShownInsets.bottom, updateLeashesForSide(ISIDE_BOTTOM, offset.bottom, mShownInsets.bottom,
mPendingInsets.bottom, params, state, mPendingAlpha); mPendingInsets.bottom, params, state, mPendingAlpha);
updateLeashesForSide(ISIDE_FLOATING, 0 /* offset */, 0 /* inset */, 0 /* maxInset */,
params, state, mPendingAlpha);
mController.applySurfaceParams(params.toArray(new SurfaceParams[params.size()])); mController.applySurfaceParams(params.toArray(new SurfaceParams[params.size()]));
mCurrentInsets = mPendingInsets; mCurrentInsets = mPendingInsets;
@@ -290,6 +302,9 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
if (insets == null) { if (insets == null) {
insets = getCurrentInsets(); insets = getCurrentInsets();
} }
if (hasZeroInsetsIme()) {
return insets;
}
return Insets.max(Insets.min(insets, mShownInsets), mHiddenInsets); return Insets.max(Insets.min(insets, mShownInsets), mHiddenInsets);
} }
@@ -313,17 +328,19 @@ public class InsetsAnimationControlImpl implements WindowInsetsAnimationControll
mTmpFrame.set(source.getFrame()); mTmpFrame.set(source.getFrame());
addTranslationToMatrix(side, offset, mTmpMatrix, mTmpFrame); addTranslationToMatrix(side, offset, mTmpMatrix, mTmpFrame);
state.getSource(source.getType()).setVisible(side == ISIDE_FLOATING || inset != 0); final boolean visible = mHasZeroInsetsIme && side == ISIDE_BOTTOM
? (mAnimationType == ANIMATION_TYPE_SHOW ? true : !mFinished)
: inset != 0;
state.getSource(source.getType()).setVisible(visible);
state.getSource(source.getType()).setFrame(mTmpFrame); state.getSource(source.getType()).setFrame(mTmpFrame);
// If the system is controlling the insets source, the leash can be null. // If the system is controlling the insets source, the leash can be null.
if (leash != null) { if (leash != null) {
SurfaceParams params = new SurfaceParams.Builder(leash) SurfaceParams params = new SurfaceParams.Builder(leash)
.withAlpha(side == ISIDE_FLOATING ? 1 : alpha) .withAlpha(alpha)
.withMatrix(mTmpMatrix) .withMatrix(mTmpMatrix)
.withVisibility(side == ISIDE_FLOATING .withVisibility(visible)
? mShownOnFinish
: inset != 0 /* visible */)
.build(); .build();
surfaceParams.add(params); surfaceParams.add(params);
} }

View File

@@ -162,6 +162,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
*/ */
@Nullable @Nullable
String getRootViewTitle(); String getRootViewTitle();
/** @see ViewRootImpl#dipToPx */
int dipToPx(int dips);
} }
private static final String TAG = "InsetsController"; private static final String TAG = "InsetsController";
@@ -254,6 +257,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
public static class InternalAnimationControlListener public static class InternalAnimationControlListener
implements WindowInsetsAnimationControlListener { implements WindowInsetsAnimationControlListener {
/** The amount IME will move up/down when animating in floating mode. */
protected static final int FLOATING_IME_BOTTOM_INSET = -80;
private WindowInsetsAnimationController mController; private WindowInsetsAnimationController mController;
private ValueAnimator mAnimator; private ValueAnimator mAnimator;
private final boolean mShow; private final boolean mShow;
@@ -261,6 +267,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private final @InsetsType int mRequestedTypes; private final @InsetsType int mRequestedTypes;
private final long mDurationMs; private final long mDurationMs;
private final boolean mDisable; private final boolean mDisable;
private final int mFloatingImeBottomInset;
private ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal = private ThreadLocal<AnimationHandler> mSfAnimationHandlerThreadLocal =
new ThreadLocal<AnimationHandler>() { new ThreadLocal<AnimationHandler>() {
@@ -273,12 +280,13 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}; };
public InternalAnimationControlListener(boolean show, boolean hasAnimationCallbacks, public InternalAnimationControlListener(boolean show, boolean hasAnimationCallbacks,
int requestedTypes, boolean disable) { int requestedTypes, boolean disable, int floatingImeBottomInset) {
mShow = show; mShow = show;
mHasAnimationCallbacks = hasAnimationCallbacks; mHasAnimationCallbacks = hasAnimationCallbacks;
mRequestedTypes = requestedTypes; mRequestedTypes = requestedTypes;
mDurationMs = calculateDurationMs(); mDurationMs = calculateDurationMs();
mDisable = disable; mDisable = disable;
mFloatingImeBottomInset = floatingImeBottomInset;
} }
@Override @Override
@@ -293,12 +301,19 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
mAnimator = ValueAnimator.ofFloat(0f, 1f); mAnimator = ValueAnimator.ofFloat(0f, 1f);
mAnimator.setDuration(mDurationMs); mAnimator.setDuration(mDurationMs);
mAnimator.setInterpolator(new LinearInterpolator()); mAnimator.setInterpolator(new LinearInterpolator());
Insets hiddenInsets = controller.getHiddenStateInsets();
// IME with zero insets is a special case: it will animate-in from offscreen and end
// with final insets of zero and vice-versa.
hiddenInsets = controller.hasZeroInsetsIme()
? Insets.of(hiddenInsets.left, hiddenInsets.top, hiddenInsets.right,
mFloatingImeBottomInset)
: hiddenInsets;
Insets start = mShow Insets start = mShow
? controller.getHiddenStateInsets() ? hiddenInsets
: controller.getShownStateInsets(); : controller.getShownStateInsets();
Insets end = mShow Insets end = mShow
? controller.getShownStateInsets() ? controller.getShownStateInsets()
: controller.getHiddenStateInsets(); : hiddenInsets;
Interpolator insetsInterpolator = getInterpolator(); Interpolator insetsInterpolator = getInterpolator();
Interpolator alphaInterpolator = getAlphaInterpolator(); Interpolator alphaInterpolator = getAlphaInterpolator();
mAnimator.addUpdateListener(animation -> { mAnimator.addUpdateListener(animation -> {
@@ -1173,7 +1188,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
boolean hasAnimationCallbacks = mHost.hasAnimationCallbacks(); boolean hasAnimationCallbacks = mHost.hasAnimationCallbacks();
final InternalAnimationControlListener listener = new InternalAnimationControlListener( final InternalAnimationControlListener listener = new InternalAnimationControlListener(
show, hasAnimationCallbacks, types, mAnimationsDisabled); show, hasAnimationCallbacks, types, mAnimationsDisabled,
mHost.dipToPx(InternalAnimationControlListener.FLOATING_IME_BOTTOM_INSET));
// Show/hide animations always need to be relative to the display frame, in order that shown // Show/hide animations always need to be relative to the display frame, in order that shown
// and hidden state insets are correct. // and hidden state insets are correct.

View File

@@ -2315,7 +2315,7 @@ public final class ViewRootImpl implements ViewParent,
|| lp.type == TYPE_VOLUME_OVERLAY; || lp.type == TYPE_VOLUME_OVERLAY;
} }
private int dipToPx(int dip) { int dipToPx(int dip) {
final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics(); final DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();
return (int) (displayMetrics.density * dip + 0.5f); return (int) (displayMetrics.density * dip + 0.5f);
} }

View File

@@ -228,4 +228,12 @@ public class ViewRootInsetsControllerHost implements InsetsController.Host {
} }
return mViewRoot.getTitle().toString(); return mViewRoot.getTitle().toString();
} }
@Override
public int dipToPx(int dips) {
if (mViewRoot != null) {
return mViewRoot.dipToPx(dips);
}
return 0;
}
} }

View File

@@ -181,4 +181,11 @@ public interface WindowInsetsAnimationController {
* @return {@code true} if the instance is cancelled, {@code false} otherwise. * @return {@code true} if the instance is cancelled, {@code false} otherwise.
*/ */
boolean isCancelled(); boolean isCancelled();
/**
* @hide
* @return {@code true} when controller controls IME and IME has no insets (floating,
* fullscreen or non-overlapping).
*/
boolean hasZeroInsetsIme();
} }

View File

@@ -387,7 +387,10 @@ class InsetsPolicy {
InsetsPolicyAnimationControlCallbacks mControlCallbacks; InsetsPolicyAnimationControlCallbacks mControlCallbacks;
InsetsPolicyAnimationControlListener(boolean show, Runnable finishCallback, int types) { InsetsPolicyAnimationControlListener(boolean show, Runnable finishCallback, int types) {
super(show, false /* hasCallbacks */, types, false /* disable */);
super(show, false /* hasCallbacks */, types, false /* disable */,
(int) (mDisplayContent.getDisplayMetrics().density * FLOATING_IME_BOTTOM_INSET
+ 0.5f));
mFinishCallback = finishCallback; mFinishCallback = finishCallback;
mControlCallbacks = new InsetsPolicyAnimationControlCallbacks(this); mControlCallbacks = new InsetsPolicyAnimationControlCallbacks(this);
} }