diff options
| author | Tiger Huang <tigerhuang@google.com> | 2020-06-19 00:12:55 +0800 |
|---|---|---|
| committer | Tiger Huang <tigerhuang@google.com> | 2020-06-23 00:58:05 +0800 |
| commit | 618dbe022ff715cadff46e1d4102b2f0715e85ea (patch) | |
| tree | 4b6a857d31e0866870df0a70bb29df988e3a2aac /core/java/android/view/InsetsController.java | |
| parent | 5d544ddff061eafa2adfa2d00cf9dd5e663f5cd0 (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.java | 73 |
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(); |
