51
51
public class PlatformViewsController implements PlatformViewsAccessibilityDelegate {
52
52
private static final String TAG = "PlatformViewsController" ;
53
53
54
- // These view types allow to issue drawing commands directly without
55
- // notifying the Android view hierarchy that a change was made .
54
+ // These view types allow out-of-band drawing operation that don't notify the Android view
55
+ // hierarchy.
56
56
// To support these cases, Flutter hosts the embedded view in a VirtualDisplay,
57
57
// and binds the VirtualDisplay to a GL texture that is then composed by the engine.
58
58
// Related issue: https://github.com/flutter/flutter/issues/103630
@@ -238,8 +238,15 @@ public long createForTextureLayer(
238
238
239
239
final int physicalWidth = toPhysicalPixels (request .logicalWidth );
240
240
final int physicalHeight = toPhysicalPixels (request .logicalHeight );
241
+
242
+ // Case 1. Add the view to a virtual display if the embedded view contains any of the
243
+ // VIEW_TYPES_REQUIRE_VD view types.
244
+ // These views allow out-of-band graphics operations that aren't notified to the Android
245
+ // view hierarchy via callbacks such as ViewParent#onDescendantInvalidated().
246
+ // The virtual display is wired up to a GL texture that is composed by the Flutter engine.
241
247
final boolean shouldUseVirtualDisplay =
242
248
ViewUtils .hasChildViewOfType (embeddedView , VIEW_TYPES_REQUIRE_VD );
249
+
243
250
if (!usesSoftwareRendering && shouldUseVirtualDisplay ) {
244
251
Log .i (TAG , "Hosting view in a virtual display for platform view: " + viewId );
245
252
// API level 20 is required to use VirtualDisplay#setSurface.
@@ -281,43 +288,42 @@ public long createForTextureLayer(
281
288
return textureEntry .id ();
282
289
}
283
290
291
+ // Case 2. Attach the view to the Android view hierarchy and record their drawing
292
+ // operations, so they can be forwarded to a GL texture that is composed by the
293
+ // Flutter engine.
294
+
284
295
// API level 23 is required to use Surface#lockHardwareCanvas().
285
296
ensureValidAndroidVersion (23 );
286
297
Log .i (TAG , "Hosting view in view hierarchy for platform view: " + viewId );
287
298
288
- PlatformViewWrapper wrapperView ;
299
+ PlatformViewWrapper viewWrapper ;
289
300
long txId ;
290
301
if (usesSoftwareRendering ) {
291
- wrapperView = new PlatformViewWrapper (context );
302
+ viewWrapper = new PlatformViewWrapper (context );
292
303
txId = -1 ;
293
304
} else {
294
305
final TextureRegistry .SurfaceTextureEntry textureEntry =
295
306
textureRegistry .createSurfaceTexture ();
296
- wrapperView = new PlatformViewWrapper (context , textureEntry );
307
+ viewWrapper = new PlatformViewWrapper (context , textureEntry );
297
308
txId = textureEntry .id ();
298
309
}
299
- wrapperView .setTouchProcessor (androidTouchProcessor );
300
- wrapperView .setBufferSize (physicalWidth , physicalHeight );
310
+ viewWrapper .setTouchProcessor (androidTouchProcessor );
311
+ viewWrapper .setBufferSize (physicalWidth , physicalHeight );
301
312
302
- final FrameLayout .LayoutParams layoutParams =
313
+ final FrameLayout .LayoutParams viewWrapperLayoutParams =
303
314
new FrameLayout .LayoutParams (physicalWidth , physicalHeight );
304
315
316
+ // Size and position the view wrapper.
305
317
final int physicalTop = toPhysicalPixels (request .logicalTop );
306
318
final int physicalLeft = toPhysicalPixels (request .logicalLeft );
307
- layoutParams .topMargin = physicalTop ;
308
- layoutParams .leftMargin = physicalLeft ;
309
- wrapperView .setLayoutParams (layoutParams );
319
+ viewWrapperLayoutParams .topMargin = physicalTop ;
320
+ viewWrapperLayoutParams .leftMargin = physicalLeft ;
321
+ viewWrapper .setLayoutParams (viewWrapperLayoutParams );
310
322
311
- final View embeddedView = platformView .getView ();
312
- if (embeddedView == null ) {
313
- throw new IllegalStateException (
314
- "PlatformView#getView() returned null, but an Android view reference was expected." );
315
- } else if (embeddedView .getParent () != null ) {
316
- throw new IllegalStateException (
317
- "The Android view returned from PlatformView#getView() was already added to a parent view." );
318
- }
323
+ // Size the embedded view.
324
+ // This isn't needed when the virtual display is used because the virtual display itself
325
+ // is sized.
319
326
embeddedView .setLayoutParams (new FrameLayout .LayoutParams (physicalWidth , physicalHeight ));
320
- embeddedView .setLayoutDirection (request .direction );
321
327
322
328
// Accessibility in the embedded view is initially disabled because if a Flutter app
323
329
// disabled accessibility in the first frame, the embedding won't receive an update to
@@ -329,17 +335,21 @@ public long createForTextureLayer(
329
335
embeddedView .setImportantForAccessibility (
330
336
View .IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS );
331
337
332
- wrapperView .addView (embeddedView );
333
- wrapperView .setOnDescendantFocusChangeListener (
338
+ // Add the embedded view to the wrapper.
339
+ viewWrapper .addView (embeddedView );
340
+
341
+ // Listen for focus changed in any subview, so the framework is notified when the platform
342
+ // view is focused.
343
+ viewWrapper .setOnDescendantFocusChangeListener (
334
344
(v , hasFocus ) -> {
335
345
if (hasFocus ) {
336
346
platformViewsChannel .invokeViewFocused (viewId );
337
347
} else if (textInputPlugin != null ) {
338
348
textInputPlugin .clearPlatformViewClient (viewId );
339
349
}
340
350
});
341
- flutterView .addView (wrapperView );
342
- viewWrappers .append (viewId , wrapperView );
351
+ flutterView .addView (viewWrapper );
352
+ viewWrappers .append (viewId , viewWrapper );
343
353
return txId ;
344
354
}
345
355
@@ -404,18 +414,18 @@ public void offset(int viewId, double top, double left) {
404
414
// texture
405
415
// is positioned by the Flutter engine, which knows where to position different types of
406
416
// layers.
407
- final PlatformViewWrapper wrapper = viewWrappers .get (viewId );
408
- if (wrapper == null ) {
417
+ final PlatformViewWrapper viewWrapper = viewWrappers .get (viewId );
418
+ if (viewWrapper == null ) {
409
419
Log .e (TAG , "Setting offset for unknown platform view with id: " + viewId );
410
420
return ;
411
421
}
412
422
final int physicalTop = toPhysicalPixels (top );
413
423
final int physicalLeft = toPhysicalPixels (left );
414
424
final FrameLayout .LayoutParams layoutParams =
415
- (FrameLayout .LayoutParams ) wrapper .getLayoutParams ();
425
+ (FrameLayout .LayoutParams ) viewWrapper .getLayoutParams ();
416
426
layoutParams .topMargin = physicalTop ;
417
427
layoutParams .leftMargin = physicalLeft ;
418
- wrapper .setLayoutParams (layoutParams );
428
+ viewWrapper .setLayoutParams (layoutParams );
419
429
}
420
430
421
431
@ Override
@@ -446,8 +456,8 @@ public void resize(
446
456
}
447
457
448
458
final PlatformView platformView = platformViews .get (viewId );
449
- final PlatformViewWrapper view = viewWrappers .get (viewId );
450
- if (platformView == null || view == null ) {
459
+ final PlatformViewWrapper viewWrapper = viewWrappers .get (viewId );
460
+ if (platformView == null || viewWrapper == null ) {
451
461
Log .e (TAG , "Resizing unknown platform view with id: " + viewId );
452
462
return ;
453
463
}
@@ -459,20 +469,21 @@ public void resize(
459
469
// Resizing the texture causes pixel stretching since the size of the GL texture used in
460
470
// the engine
461
471
// is set by the framework, but the texture buffer size is set by the platform down below.
462
- if (physicalWidth > view .getBufferWidth () || physicalHeight > view .getBufferHeight ()) {
463
- view .setBufferSize (physicalWidth , physicalHeight );
472
+ if (physicalWidth > viewWrapper .getBufferWidth ()
473
+ || physicalHeight > viewWrapper .getBufferHeight ()) {
474
+ viewWrapper .setBufferSize (physicalWidth , physicalHeight );
464
475
}
465
476
466
- final ViewGroup .LayoutParams viewWrapperLayoutParams = view .getLayoutParams ();
467
- viewWrapperLayoutParams .width = newWidth ;
468
- viewWrapperLayoutParams .height = newHeight ;
469
- view .setLayoutParams (viewWrapperLayoutParams );
477
+ final ViewGroup .LayoutParams viewWrapperLayoutParams = viewWrapper .getLayoutParams ();
478
+ viewWrapperLayoutParams .width = physicalWidth ;
479
+ viewWrapperLayoutParams .height = physicalHeight ;
480
+ viewWrapper .setLayoutParams (viewWrapperLayoutParams );
470
481
471
482
final View embeddedView = platformView .getView ();
472
483
if (embeddedView != null ) {
473
484
final ViewGroup .LayoutParams embeddedViewLayoutParams = embeddedView .getLayoutParams ();
474
- embeddedViewLayoutParams .width = newWidth ;
475
- embeddedViewLayoutParams .height = newHeight ;
485
+ embeddedViewLayoutParams .width = physicalWidth ;
486
+ embeddedViewLayoutParams .height = physicalHeight ;
476
487
embeddedView .setLayoutParams (embeddedViewLayoutParams );
477
488
}
478
489
onComplete .run (
@@ -520,12 +531,12 @@ public void setDirection(int viewId, int direction) {
520
531
Log .e (TAG , "Setting direction to an unknown view with id: " + viewId );
521
532
return ;
522
533
}
523
- final View view = platformView .getView ();
524
- if (view == null ) {
534
+ final View embeddedView = platformView .getView ();
535
+ if (embeddedView == null ) {
525
536
Log .e (TAG , "Setting direction to a null view with id: " + viewId );
526
537
return ;
527
538
}
528
- view .setLayoutDirection (direction );
539
+ embeddedView .setLayoutDirection (direction );
529
540
}
530
541
531
542
@ Override
@@ -535,12 +546,12 @@ public void clearFocus(int viewId) {
535
546
Log .e (TAG , "Clearing focus on an unknown view with id: " + viewId );
536
547
return ;
537
548
}
538
- final View view = platformView .getView ();
539
- if (view == null ) {
549
+ final View embeddedView = platformView .getView ();
550
+ if (embeddedView == null ) {
540
551
Log .e (TAG , "Clearing focus on a null view with id: " + viewId );
541
552
return ;
542
553
}
543
- view .clearFocus ();
554
+ embeddedView .clearFocus ();
544
555
}
545
556
546
557
private void ensureValidAndroidVersion (int minSdkVersion ) {
0 commit comments