Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,17 @@ class ImeSyncDeferringInsetsCallback extends WindowInsetsAnimation.Callback

private View view;
private WindowInsets lastWindowInsets;
private boolean started = false;
// True when an animation that matches deferredInsetTypes is active.
//
// While this is active, this class will capture the initial window inset
// sent into lastWindowInsets by flagging needsSave to true, and will hold
// onto the intitial inset until the animation is completed, when it will
// re-dispatch the inset change.
private boolean animating = false;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd add code comments for what these 2 are for the next maintainer

// When an animation begins, android sends a WindowInset with the final
// state of the animation. When needsSave is true, we know to capture this
// initial WindowInset.
private boolean needsSave = false;

ImeSyncDeferringInsetsCallback(
@NonNull View view, int overlayInsetTypes, int deferredInsetTypes) {
Expand All @@ -212,34 +222,38 @@ class ImeSyncDeferringInsetsCallback extends WindowInsetsAnimation.Callback
@Override
public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
this.view = view;
if (started) {
if (needsSave) {
// Store the view and insets for us in onEnd() below. This captured inset
// is not part of the animation and instead, represents the final state
// of the inset after the animation is completed. Thus, we defer the processing
// of this WindowInset until the animation completes.
lastWindowInsets = windowInsets;
needsSave = false;
}
if (animating) {
// While animation is running, we consume the insets to prevent disrupting
// the animation, which skips this implementation and calls the view's
// onApplyWindowInsets directly to avoid being consumed here.
return WindowInsets.CONSUMED;
}

// Store the view and insets for us in onEnd() below
lastWindowInsets = windowInsets;

// If no animation is happening, pass the insets on to the view's own
// inset handling.
return view.onApplyWindowInsets(windowInsets);
}

@Override
public WindowInsetsAnimation.Bounds onStart(
WindowInsetsAnimation animation, WindowInsetsAnimation.Bounds bounds) {
public void onPrepare(WindowInsetsAnimation animation) {
if ((animation.getTypeMask() & deferredInsetTypes) != 0) {
started = true;
animating = true;
needsSave = true;
}
return bounds;
}

@Override
public WindowInsets onProgress(
WindowInsets insets, List<WindowInsetsAnimation> runningAnimations) {
if (!started) {
if (!animating || needsSave) {
return insets;
}
boolean matching = false;
Expand Down Expand Up @@ -280,10 +294,10 @@ public WindowInsets onProgress(

@Override
public void onEnd(WindowInsetsAnimation animation) {
if (started && (animation.getTypeMask() & deferredInsetTypes) != 0) {
if (animating && (animation.getTypeMask() & deferredInsetTypes) != 0) {
// If we deferred the IME insets and an IME animation has finished, we need to reset
// the flags
started = false;
animating = false;

// And finally dispatch the deferred insets to the view now.
// Ideally we would just call view.requestApplyInsets() and let the normal dispatch
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -669,6 +669,8 @@ public void ime_windowInsetsSync() {
WindowInsets.Builder builder = new WindowInsets.Builder();
WindowInsets noneInsets = builder.build();

// imeInsets0, 1, and 2 contain unique IME bottom insets, and are used
// to distinguish which insets were sent at each stage.
builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 100));
builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(10, 10, 10, 40));
WindowInsets imeInsets0 = builder.build();
Expand All @@ -677,6 +679,10 @@ public void ime_windowInsetsSync() {
builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(10, 10, 10, 40));
WindowInsets imeInsets1 = builder.build();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add some comments for what 0, 1, 2 are supposed to represent? Different stages of an animation?


builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 50));
builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(10, 10, 10, 40));
WindowInsets imeInsets2 = builder.build();

builder.setInsets(WindowInsets.Type.ime(), Insets.of(0, 0, 0, 200));
builder.setInsets(WindowInsets.Type.navigationBars(), Insets.of(10, 10, 10, 0));
WindowInsets deferredInsets = builder.build();
Expand All @@ -696,6 +702,8 @@ public void ime_windowInsetsSync() {
imeSyncCallback.onPrepare(animation);
imeSyncCallback.onApplyWindowInsets(testView, deferredInsets);
imeSyncCallback.onStart(animation, null);
// Only the final state call is saved, extra calls are passed on.
imeSyncCallback.onApplyWindowInsets(testView, imeInsets2);

verify(flutterRenderer).setViewportMetrics(viewportMetricsCaptor.capture());
// No change, as deferredInset is stored to be passed in onEnd()
Expand Down Expand Up @@ -723,7 +731,7 @@ public void ime_windowInsetsSync() {
imeSyncCallback.onEnd(animation);

verify(flutterRenderer).setViewportMetrics(viewportMetricsCaptor.capture());
// Values should be of deferredInsets
// Values should be of deferredInsets, not imeInsets2
assertEquals(0, viewportMetricsCaptor.getValue().paddingBottom);
assertEquals(10, viewportMetricsCaptor.getValue().paddingTop);
assertEquals(200, viewportMetricsCaptor.getValue().viewInsetBottom);
Expand Down