-
Notifications
You must be signed in to change notification settings - Fork 6k
[Android] Fix incorrect viewInsets during keyboard animation with EdgeToEdge #39391
Changes from all commits
6945789
e63b10f
044cb13
30bfbf2
77ec64e
57c2a5f
1b3e603
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -47,9 +47,7 @@ | |
| @SuppressLint({"NewApi", "Override"}) | ||
| @Keep | ||
| class ImeSyncDeferringInsetsCallback { | ||
| private int overlayInsetTypes; | ||
| private int deferredInsetTypes; | ||
|
|
||
| private final int deferredInsetTypes = WindowInsets.Type.ime(); | ||
| private View view; | ||
| private WindowInsets lastWindowInsets; | ||
| private AnimationCallback animationCallback; | ||
|
|
@@ -67,10 +65,7 @@ class ImeSyncDeferringInsetsCallback { | |
| // initial WindowInset. | ||
| private boolean needsSave = false; | ||
|
|
||
| ImeSyncDeferringInsetsCallback( | ||
| @NonNull View view, int overlayInsetTypes, int deferredInsetTypes) { | ||
| this.overlayInsetTypes = overlayInsetTypes; | ||
| this.deferredInsetTypes = deferredInsetTypes; | ||
| ImeSyncDeferringInsetsCallback(@NonNull View view) { | ||
| this.view = view; | ||
| this.animationCallback = new AnimationCallback(); | ||
| this.insetsListener = new InsetsListener(); | ||
|
|
@@ -131,24 +126,24 @@ public WindowInsets onProgress( | |
| if (!matching) { | ||
| return insets; | ||
| } | ||
|
|
||
| // The IME insets include the height of the navigation bar. If the app isn't laid out behind | ||
| // the navigation bar, this causes the IME insets to be too large during the animation. | ||
| // To fix this, we subtract the navigationBars bottom inset if the system UI flags for laying | ||
| // out behind the navigation bar aren't present. | ||
| int excludedInsets = 0; | ||
| int systemUiFlags = view.getWindowSystemUiVisibility(); | ||
| if ((systemUiFlags & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0 | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Without committing you to building it do you think we need to do a similar evaluation for status bar and the top insets?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think that'll be necessary as the status bar visibility and top insets didn't affect the keyboard animation in my testing.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. But it would impact any animation coming from the top like keyboards impact animations coming from the bottom. Right? If for example the status bar was present our code would behave differently than if status bar was overlayed. I am thinking of flutter/flutter#118761
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah interesting, I'm not sure on this one but WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE is one of the new APIs introduced in API 30, so I wonder if it's a conflict with the deprecated system UI flags currently in use, rather than an issue with keyboard animation.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @gmackall this is something to keep in mind. |
||
| && (systemUiFlags & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) { | ||
| excludedInsets = insets.getInsets(WindowInsets.Type.navigationBars()).bottom; | ||
| } | ||
|
|
||
| WindowInsets.Builder builder = new WindowInsets.Builder(lastWindowInsets); | ||
| // Overlay the ime-only insets with the full insets. | ||
| // | ||
| // The IME insets passed in by onProgress assumes that the entire animation | ||
| // occurs above any present navigation and status bars. This causes the | ||
| // IME inset to be too large for the animation. To remedy this, we merge the | ||
| // IME inset with other insets present via a subtract + reLu, which causes the | ||
| // IME inset to be overlaid with any bars present. | ||
| Insets newImeInsets = | ||
| Insets.of( | ||
| 0, | ||
| 0, | ||
| 0, | ||
| Math.max( | ||
| insets.getInsets(deferredInsetTypes).bottom | ||
| - insets.getInsets(overlayInsetTypes).bottom, | ||
| 0)); | ||
| 0, 0, 0, Math.max(insets.getInsets(deferredInsetTypes).bottom - excludedInsets, 0)); | ||
| builder.setInsets(deferredInsetTypes, newImeInsets); | ||
|
|
||
| // Directly call onApplyWindowInsets of the view as we do not want to pass through | ||
| // the onApplyWindowInsets defined in this class, which would consume the insets | ||
| // as if they were a non-animation inset change and cache it for re-dispatch in | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.