17
17
import android .view .KeyEvent ;
18
18
import android .view .MotionEvent ;
19
19
import android .view .WindowInsets ;
20
+ import android .view .WindowManager ;
20
21
import android .view .inputmethod .EditorInfo ;
21
22
import android .view .inputmethod .InputConnection ;
22
- import android .view .inputmethod .InputMethod ;
23
- import android .view .inputmethod .InputMethodManager ;
24
23
import android .widget .FrameLayout ;
25
24
26
25
import java .util .ArrayList ;
30
29
import io .flutter .embedding .engine .FlutterEngine ;
31
30
import io .flutter .embedding .engine .renderer .FlutterRenderer ;
32
31
import io .flutter .plugin .editing .TextInputPlugin ;
32
+ import io .flutter .view .VsyncWaiter ;
33
33
34
34
/**
35
35
* Displays a Flutter UI on an Android device.
@@ -77,6 +77,9 @@ public class FlutterView extends FrameLayout {
77
77
@ Nullable
78
78
private AndroidKeyProcessor androidKeyProcessor ;
79
79
80
+ // Directly implemented View behavior that communicates with Flutter.
81
+ private final FlutterRenderer .ViewportMetrics viewportMetrics = new FlutterRenderer .ViewportMetrics ();
82
+
80
83
/**
81
84
* Constructs a {@code FlutterSurfaceView} programmatically, without any XML attributes.
82
85
*
@@ -158,8 +161,10 @@ protected void onConfigurationChanged(Configuration newConfig) {
158
161
*/
159
162
@ Override
160
163
protected void onSizeChanged (int width , int height , int oldWidth , int oldHeight ) {
161
- // TODO(mattcarroll): hookup to viewport metrics.
162
164
super .onSizeChanged (width , height , oldWidth , oldHeight );
165
+ viewportMetrics .width = width ;
166
+ viewportMetrics .height = height ;
167
+ sendViewportMetricsToFlutter ();
163
168
}
164
169
165
170
/**
@@ -174,8 +179,22 @@ protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
174
179
*/
175
180
@ Override
176
181
public final WindowInsets onApplyWindowInsets (WindowInsets insets ) {
177
- // TODO(mattcarroll): hookup to Flutter metrics.
178
- return insets ;
182
+ WindowInsets newInsets = super .onApplyWindowInsets (insets );
183
+
184
+ // Status bar (top) and left/right system insets should partially obscure the content (padding).
185
+ viewportMetrics .paddingTop = insets .getSystemWindowInsetTop ();
186
+ viewportMetrics .paddingRight = insets .getSystemWindowInsetRight ();
187
+ viewportMetrics .paddingBottom = 0 ;
188
+ viewportMetrics .paddingLeft = insets .getSystemWindowInsetLeft ();
189
+
190
+ // Bottom system inset (keyboard) should adjust scrollable bottom edge (inset).
191
+ viewportMetrics .viewInsetTop = 0 ;
192
+ viewportMetrics .viewInsetRight = 0 ;
193
+ viewportMetrics .viewInsetBottom = insets .getSystemWindowInsetBottom ();
194
+ viewportMetrics .viewInsetLeft = 0 ;
195
+ sendViewportMetricsToFlutter ();
196
+
197
+ return newInsets ;
179
198
}
180
199
181
200
/**
@@ -188,8 +207,23 @@ public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
188
207
@ Override
189
208
@ SuppressWarnings ("deprecation" )
190
209
protected boolean fitSystemWindows (Rect insets ) {
191
- // TODO(mattcarroll): hookup to Flutter metrics.
192
- return super .fitSystemWindows (insets );
210
+ if (Build .VERSION .SDK_INT <= Build .VERSION_CODES .KITKAT ) {
211
+ // Status bar, left/right system insets partially obscure content (padding).
212
+ viewportMetrics .paddingTop = insets .top ;
213
+ viewportMetrics .paddingRight = insets .right ;
214
+ viewportMetrics .paddingBottom = 0 ;
215
+ viewportMetrics .paddingLeft = insets .left ;
216
+
217
+ // Bottom system inset (keyboard) should adjust scrollable bottom edge (inset).
218
+ viewportMetrics .viewInsetTop = 0 ;
219
+ viewportMetrics .viewInsetRight = 0 ;
220
+ viewportMetrics .viewInsetBottom = insets .bottom ;
221
+ viewportMetrics .viewInsetLeft = 0 ;
222
+ sendViewportMetricsToFlutter ();
223
+ return true ;
224
+ } else {
225
+ return super .fitSystemWindows (insets );
226
+ }
193
227
}
194
228
//------- End: Process View configuration that Flutter cares about. --------
195
229
@@ -312,13 +346,16 @@ public boolean onHoverEvent(MotionEvent event) {
312
346
* {@link FlutterEngine}.
313
347
*/
314
348
public void attachToFlutterEngine (@ NonNull FlutterEngine flutterEngine ) {
349
+ Log .d (TAG , "attachToFlutterEngine()" );
315
350
if (isAttachedToFlutterEngine ()) {
316
351
if (flutterEngine == this .flutterEngine ) {
317
352
// We are already attached to this FlutterEngine
353
+ Log .d (TAG , "Already attached to this engine. Doing nothing." );
318
354
return ;
319
355
}
320
356
321
357
// Detach from a previous FlutterEngine so we can attach to this new one.
358
+ Log .d (TAG , "Currently attached to a different engine. Detaching." );
322
359
detachFromFlutterEngine ();
323
360
}
324
361
@@ -346,6 +383,7 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) {
346
383
// Push View and Context related information from Android to Flutter.
347
384
sendUserSettingsToFlutter ();
348
385
sendLocalesToFlutter (getResources ().getConfiguration ());
386
+ sendViewportMetricsToFlutter ();
349
387
}
350
388
351
389
/**
@@ -359,7 +397,9 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) {
359
397
* {@link FlutterEngine}.
360
398
*/
361
399
public void detachFromFlutterEngine () {
400
+ Log .d (TAG , "detachFromFlutterEngine()" );
362
401
if (!isAttachedToFlutterEngine ()) {
402
+ Log .d (TAG , "Not attached to an engine. Doing nothing." );
363
403
return ;
364
404
}
365
405
Log .d (TAG , "Detaching from Flutter Engine" );
@@ -422,6 +462,18 @@ private void sendUserSettingsToFlutter() {
422
462
.send ();
423
463
}
424
464
465
+ // TODO(mattcarroll): consider introducing a system channel for this communication instead of JNI
466
+ private void sendViewportMetricsToFlutter () {
467
+ Log .d (TAG , "sendViewportMetricsToFlutter()" );
468
+ if (!isAttachedToFlutterEngine ()) {
469
+ Log .w (TAG , "Tried to send viewport metrics from Android to Flutter but this FlutterView was not attached to a FlutterEngine." );
470
+ return ;
471
+ }
472
+
473
+ viewportMetrics .devicePixelRatio = getResources ().getDisplayMetrics ().density ;
474
+ flutterEngine .getRenderer ().setViewportMetrics (viewportMetrics );
475
+ }
476
+
425
477
/**
426
478
* Render modes for a {@link FlutterView}.
427
479
*/
0 commit comments