1717import android .view .KeyEvent ;
1818import android .view .MotionEvent ;
1919import android .view .WindowInsets ;
20+ import android .view .WindowManager ;
2021import android .view .inputmethod .EditorInfo ;
2122import android .view .inputmethod .InputConnection ;
22- import android .view .inputmethod .InputMethod ;
23- import android .view .inputmethod .InputMethodManager ;
2423import android .widget .FrameLayout ;
2524
2625import java .util .ArrayList ;
3029import io .flutter .embedding .engine .FlutterEngine ;
3130import io .flutter .embedding .engine .renderer .FlutterRenderer ;
3231import io .flutter .plugin .editing .TextInputPlugin ;
32+ import io .flutter .view .VsyncWaiter ;
3333
3434/**
3535 * Displays a Flutter UI on an Android device.
@@ -77,6 +77,9 @@ public class FlutterView extends FrameLayout {
7777 @ Nullable
7878 private AndroidKeyProcessor androidKeyProcessor ;
7979
80+ // Directly implemented View behavior that communicates with Flutter.
81+ private final FlutterRenderer .ViewportMetrics viewportMetrics = new FlutterRenderer .ViewportMetrics ();
82+
8083 /**
8184 * Constructs a {@code FlutterSurfaceView} programmatically, without any XML attributes.
8285 *
@@ -158,8 +161,10 @@ protected void onConfigurationChanged(Configuration newConfig) {
158161 */
159162 @ Override
160163 protected void onSizeChanged (int width , int height , int oldWidth , int oldHeight ) {
161- // TODO(mattcarroll): hookup to viewport metrics.
162164 super .onSizeChanged (width , height , oldWidth , oldHeight );
165+ viewportMetrics .width = width ;
166+ viewportMetrics .height = height ;
167+ sendViewportMetricsToFlutter ();
163168 }
164169
165170 /**
@@ -174,8 +179,22 @@ protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
174179 */
175180 @ Override
176181 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 ;
179198 }
180199
181200 /**
@@ -188,8 +207,23 @@ public final WindowInsets onApplyWindowInsets(WindowInsets insets) {
188207 @ Override
189208 @ SuppressWarnings ("deprecation" )
190209 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+ }
193227 }
194228 //------- End: Process View configuration that Flutter cares about. --------
195229
@@ -312,13 +346,16 @@ public boolean onHoverEvent(MotionEvent event) {
312346 * {@link FlutterEngine}.
313347 */
314348 public void attachToFlutterEngine (@ NonNull FlutterEngine flutterEngine ) {
349+ Log .d (TAG , "attachToFlutterEngine()" );
315350 if (isAttachedToFlutterEngine ()) {
316351 if (flutterEngine == this .flutterEngine ) {
317352 // We are already attached to this FlutterEngine
353+ Log .d (TAG , "Already attached to this engine. Doing nothing." );
318354 return ;
319355 }
320356
321357 // Detach from a previous FlutterEngine so we can attach to this new one.
358+ Log .d (TAG , "Currently attached to a different engine. Detaching." );
322359 detachFromFlutterEngine ();
323360 }
324361
@@ -346,6 +383,7 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) {
346383 // Push View and Context related information from Android to Flutter.
347384 sendUserSettingsToFlutter ();
348385 sendLocalesToFlutter (getResources ().getConfiguration ());
386+ sendViewportMetricsToFlutter ();
349387 }
350388
351389 /**
@@ -359,7 +397,9 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) {
359397 * {@link FlutterEngine}.
360398 */
361399 public void detachFromFlutterEngine () {
400+ Log .d (TAG , "detachFromFlutterEngine()" );
362401 if (!isAttachedToFlutterEngine ()) {
402+ Log .d (TAG , "Not attached to an engine. Doing nothing." );
363403 return ;
364404 }
365405 Log .d (TAG , "Detaching from Flutter Engine" );
@@ -422,6 +462,18 @@ private void sendUserSettingsToFlutter() {
422462 .send ();
423463 }
424464
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+
425477 /**
426478 * Render modes for a {@link FlutterView}.
427479 */
0 commit comments