summaryrefslogtreecommitdiff
path: root/core/java/android/view/InsetsController.java
diff options
context:
space:
mode:
authorTiger Huang <tigerhuang@google.com>2020-06-19 00:12:55 +0800
committerTiger Huang <tigerhuang@google.com>2020-06-23 00:58:05 +0800
commit618dbe022ff715cadff46e1d4102b2f0715e85ea (patch)
tree4b6a857d31e0866870df0a70bb29df988e3a2aac /core/java/android/view/InsetsController.java
parent5d544ddff061eafa2adfa2d00cf9dd5e663f5cd0 (diff)
Disable user animations on insets whose visible frame is empty (refined)
Floating IME or fullscreen IME won't cause insets (except the area overlapped with navigation bar). It doesn't make much sense to let apps move the IME at these cases. Fix: 157777145 Test: atest InsetsSourceConsumerTest GlobalActionsImeTest ImeInsetsControllerTest Change-Id: Id70f59be7653beedc02d6c8bc3b1bd50a357f4fe
Diffstat (limited to 'core/java/android/view/InsetsController.java')
-rw-r--r--core/java/android/view/InsetsController.java73
1 files changed, 64 insertions, 9 deletions
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index dd48d554f296..0e250c4849b5 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -492,6 +492,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
/** Set of inset types for which an animation was started since last resetting this field */
private @InsetsType int mLastStartedAnimTypes;
+ /** Set of inset types which cannot be controlled by the user animation */
+ private @InsetsType int mDisabledUserAnimationInsetsTypes;
+
+ private Runnable mInvokeControllableInsetsChangedListeners =
+ this::invokeControllableInsetsChangedListeners;
+
public InsetsController(Host host) {
this(host, (controller, type) -> {
if (type == ITYPE_IME) {
@@ -606,22 +612,57 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private void updateState(InsetsState newState) {
mState.setDisplayFrame(newState.getDisplayFrame());
- for (int i = 0; i < InsetsState.SIZE; i++) {
- InsetsSource source = newState.peekSource(i);
- if (source == null) continue;;
- getSourceConsumer(source.getType()).updateSource(source);
+ @InsetsType int disabledUserAnimationTypes = 0;
+ @InsetsType int[] cancelledUserAnimationTypes = {0};
+ for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
+ InsetsSource source = newState.peekSource(type);
+ if (source == null) continue;
+ @AnimationType int animationType = getAnimationType(type);
+ if (!source.isUserControllable()) {
+ @InsetsType int insetsType = toPublicType(type);
+ // The user animation is not allowed when visible frame is empty.
+ disabledUserAnimationTypes |= insetsType;
+ if (animationType == ANIMATION_TYPE_USER) {
+ // Existing user animation needs to be cancelled.
+ animationType = ANIMATION_TYPE_NONE;
+ cancelledUserAnimationTypes[0] |= insetsType;
+ }
+ }
+ getSourceConsumer(type).updateSource(source, animationType);
}
- for (int i = 0; i < InsetsState.SIZE; i++) {
- InsetsSource source = mState.peekSource(i);
+ for (@InternalInsetsType int type = 0; type < InsetsState.SIZE; type++) {
+ InsetsSource source = mState.peekSource(type);
if (source == null) continue;
- if (newState.peekSource(source.getType()) == null) {
- mState.removeSource(source.getType());
+ if (newState.peekSource(type) == null) {
+ mState.removeSource(type);
}
}
if (mCaptionInsetsHeight != 0) {
mState.getSource(ITYPE_CAPTION_BAR).setFrame(new Rect(mFrame.left, mFrame.top,
mFrame.right, mFrame.top + mCaptionInsetsHeight));
}
+
+ updateDisabledUserAnimationTypes(disabledUserAnimationTypes);
+
+ if (cancelledUserAnimationTypes[0] != 0) {
+ mHandler.post(() -> show(cancelledUserAnimationTypes[0]));
+ }
+ }
+
+ private void updateDisabledUserAnimationTypes(@InsetsType int disabledUserAnimationTypes) {
+ @InsetsType int diff = mDisabledUserAnimationInsetsTypes ^ disabledUserAnimationTypes;
+ if (diff != 0) {
+ for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
+ InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
+ if (consumer.getControl() != null
+ && (toPublicType(consumer.getType()) & diff) != 0) {
+ mHandler.removeCallbacks(mInvokeControllableInsetsChangedListeners);
+ mHandler.post(mInvokeControllableInsetsChangedListeners);
+ break;
+ }
+ }
+ mDisabledUserAnimationInsetsTypes = disabledUserAnimationTypes;
+ }
}
private boolean captionInsetsUnchanged() {
@@ -825,6 +866,18 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
+ " while an existing " + Type.toString(mTypesBeingCancelled)
+ " is being cancelled.");
}
+ if (animationType == ANIMATION_TYPE_USER) {
+ final @InsetsType int disabledTypes = types & mDisabledUserAnimationInsetsTypes;
+ if (DEBUG) Log.d(TAG, "user animation disabled types: " + disabledTypes);
+ types &= ~mDisabledUserAnimationInsetsTypes;
+
+ if (fromIme && (disabledTypes & ime()) != 0
+ && !mState.getSource(ITYPE_IME).isVisible()) {
+ // We've requested IMM to show IME, but the IME is not controllable. We need to
+ // cancel the request.
+ getSourceConsumer(ITYPE_IME).hide(true, animationType);
+ }
+ }
if (types == 0) {
// nothing to animate.
listener.onCancelled(null);
@@ -1297,7 +1350,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
@InsetsType int result = 0;
for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
- if (consumer.getControl() != null) {
+ InsetsSource source = mState.peekSource(consumer.mType);
+ if (consumer.getControl() != null && source != null && source.isUserControllable()) {
result |= toPublicType(consumer.mType);
}
}
@@ -1308,6 +1362,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
* @return The types that are now animating due to a listener invoking control/show/hide
*/
private @InsetsType int invokeControllableInsetsChangedListeners() {
+ mHandler.removeCallbacks(mInvokeControllableInsetsChangedListeners);
mLastStartedAnimTypes = 0;
@InsetsType int types = calculateControllableTypes();
int size = mControllableInsetsChangedListeners.size();