5package io.flutter.plugin.editing;
7import static io.flutter.Build.API_LEVELS;
9import android.annotation.SuppressLint;
10import android.annotation.TargetApi;
13import android.view.WindowInsets;
14import android.view.WindowInsetsAnimation;
15import androidx.annotation.Keep;
16import androidx.annotation.NonNull;
17import androidx.annotation.RequiresApi;
18import androidx.annotation.VisibleForTesting;
47@TargetApi(API_LEVELS.API_30)
48@RequiresApi(API_LEVELS.API_30)
49@SuppressLint({
"NewApi",
"Override"})
52 private final int deferredInsetTypes = WindowInsets.Type.ime();
54 private WindowInsets lastWindowInsets;
55 private AnimationCallback animationCallback;
56 private InsetsListener insetsListener;
64 private boolean animating =
false;
74 private boolean needsSave =
false;
78 this.animationCallback =
new AnimationCallback();
79 this.insetsListener =
new InsetsListener();
84 view.setWindowInsetsAnimationCallback(animationCallback);
85 view.setOnApplyWindowInsetsListener(insetsListener);
90 view.setWindowInsetsAnimationCallback(
null);
91 view.setOnApplyWindowInsetsListener(
null);
96 return insetsListener;
101 return animationCallback;
108 private class AnimationCallback
extends WindowInsetsAnimation.
Callback {
109 AnimationCallback() {
110 super(WindowInsetsAnimation.Callback.DISPATCH_MODE_CONTINUE_ON_SUBTREE);
114 public void onPrepare(WindowInsetsAnimation animation) {
116 if ((animation.getTypeMask() & deferredInsetTypes) != 0) {
122 public WindowInsets onProgress(
124 if (!animating || needsSave) {
127 boolean matching =
false;
128 for (WindowInsetsAnimation animation : runningAnimations) {
129 if ((animation.getTypeMask() & deferredInsetTypes) != 0) {
142 int excludedInsets = 0;
143 int systemUiFlags = view.getWindowSystemUiVisibility();
144 if ((systemUiFlags & View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION) == 0
145 && (systemUiFlags & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0) {
146 excludedInsets = insets.getInsets(WindowInsets.Type.navigationBars()).bottom;
149 WindowInsets.Builder
builder =
new WindowInsets.Builder(lastWindowInsets);
150 Insets newImeInsets =
152 0, 0, 0, Math.max(insets.getInsets(deferredInsetTypes).bottom - excludedInsets, 0));
153 builder.setInsets(deferredInsetTypes, newImeInsets);
159 view.onApplyWindowInsets(
builder.build());
164 public void onEnd(WindowInsetsAnimation animation) {
165 if (animating && (animation.getTypeMask() & deferredInsetTypes) != 0) {
174 if (lastWindowInsets !=
null && view !=
null) {
175 view.dispatchApplyWindowInsets(lastWindowInsets);
181 private class InsetsListener
implements View.OnApplyWindowInsetsListener {
183 public WindowInsets onApplyWindowInsets(View view, WindowInsets windowInsets) {
184 ImeSyncDeferringInsetsCallback.this.view = view;
190 lastWindowInsets = windowInsets;
197 return WindowInsets.CONSUMED;
202 return view.onApplyWindowInsets(windowInsets);
WindowInsetsAnimation.Callback getAnimationCallback()
View.OnApplyWindowInsetsListener getInsetsListener()
ImeSyncDeferringInsetsCallback(@NonNull View view)
std::function< void(MTLRenderPipelineDescriptor *)> Callback