@@ -79,9 +79,20 @@ public class PlatformViewsController implements PlatformViewsAccessibilityDelega
79
79
// it is associated with(e.g if a platform view creates other views in the same virtual display.
80
80
private final HashMap <Context , View > contextToPlatformView ;
81
81
82
- private final SparseArray <PlatformViewsChannel .PlatformViewCreationRequest > platformViewRequests ;
82
+ // The views returned by `PlatformView#getView()`.
83
+ //
84
+ // This only applies to hybrid composition.
83
85
private final SparseArray <View > platformViews ;
84
- private final SparseArray <FlutterMutatorView > mutatorViews ;
86
+
87
+ // The platform view parents that are appended to `FlutterView`.
88
+ // If an entry in `platformViews` doesn't have an entry in this array, the platform view isn't
89
+ // in the view hierarchy.
90
+ //
91
+ // This view provides a wrapper that applies scene builder operations to the platform view.
92
+ // For example, a transform matrix, or setting opacity on the platform view layer.
93
+ //
94
+ // This is only applies to hybrid composition.
95
+ private final SparseArray <FlutterMutatorView > platformViewParent ;
85
96
86
97
// Map of unique IDs to views that render overlay layers.
87
98
private final SparseArray <FlutterImageView > overlayLayerViews ;
@@ -107,25 +118,57 @@ public class PlatformViewsController implements PlatformViewsAccessibilityDelega
107
118
@ Override
108
119
public void createAndroidViewForPlatformView (
109
120
@ NonNull PlatformViewsChannel .PlatformViewCreationRequest request ) {
110
- // API level 19 is required for android.graphics.ImageReader.
121
+ // API level 19 is required for ` android.graphics.ImageReader` .
111
122
ensureValidAndroidVersion (Build .VERSION_CODES .KITKAT );
112
- platformViewRequests .put (request .viewId , request );
123
+
124
+ if (!validateDirection (request .direction )) {
125
+ throw new IllegalStateException (
126
+ "Trying to create a view with unknown direction value: "
127
+ + request .direction
128
+ + "(view id: "
129
+ + request .viewId
130
+ + ")" );
131
+ }
132
+
133
+ final PlatformViewFactory factory = registry .getFactory (request .viewType );
134
+ if (factory == null ) {
135
+ throw new IllegalStateException (
136
+ "Trying to create a platform view of unregistered type: " + request .viewType );
137
+ }
138
+
139
+ Object createParams = null ;
140
+ if (request .params != null ) {
141
+ createParams = factory .getCreateArgsCodec ().decodeMessage (request .params );
142
+ }
143
+
144
+ final PlatformView platformView = factory .create (context , request .viewId , createParams );
145
+ final View view = platformView .getView ();
146
+ if (view == null ) {
147
+ throw new IllegalStateException (
148
+ "PlatformView#getView() returned null, but an Android view reference was expected." );
149
+ }
150
+ if (view .getParent () != null ) {
151
+ throw new IllegalStateException (
152
+ "The Android view returned from PlatformView#getView() was already added to a parent view." );
153
+ }
154
+ platformViews .put (request .viewId , view );
113
155
}
114
156
115
157
@ Override
116
158
public void disposeAndroidViewForPlatformView (int viewId ) {
117
159
// Hybrid view.
118
- if (platformViewRequests .get (viewId ) != null ) {
119
- platformViewRequests .remove (viewId );
120
- }
121
-
122
160
final View platformView = platformViews .get (viewId );
161
+ final FlutterMutatorView parentView = platformViewParent .get (viewId );
123
162
if (platformView != null ) {
124
- final FlutterMutatorView mutatorView = mutatorViews . get ( viewId );
125
- mutatorView .removeView (platformView );
126
- (( FlutterView ) flutterView ). removeView ( mutatorView );
163
+ if ( parentView != null ) {
164
+ parentView .removeView (platformView );
165
+ }
127
166
platformViews .remove (viewId );
128
- mutatorViews .remove (viewId );
167
+ }
168
+
169
+ if (parentView != null ) {
170
+ ((FlutterView ) flutterView ).removeView (parentView );
171
+ platformViewParent .remove (viewId );
129
172
}
130
173
}
131
174
@@ -378,9 +421,8 @@ public PlatformViewsController() {
378
421
currentFrameUsedOverlayLayerIds = new HashSet <>();
379
422
currentFrameUsedPlatformViewIds = new HashSet <>();
380
423
381
- platformViewRequests = new SparseArray <>();
382
424
platformViews = new SparseArray <>();
383
- mutatorViews = new SparseArray <>();
425
+ platformViewParent = new SparseArray <>();
384
426
385
427
motionEventTracker = MotionEventTracker .getInstance ();
386
428
}
@@ -651,55 +693,20 @@ private void initializeRootImageViewIfNeeded() {
651
693
652
694
@ VisibleForTesting
653
695
void initializePlatformViewIfNeeded (int viewId ) {
654
- if (platformViews .get (viewId ) != null ) {
655
- return ;
656
- }
657
-
658
- PlatformViewsChannel .PlatformViewCreationRequest request = platformViewRequests .get (viewId );
659
- if (request == null ) {
660
- throw new IllegalStateException (
661
- "Platform view hasn't been initialized from the platform view channel." );
662
- }
663
-
664
- if (!validateDirection (request .direction )) {
665
- throw new IllegalStateException (
666
- "Trying to create a view with unknown direction value: "
667
- + request .direction
668
- + "(view id: "
669
- + viewId
670
- + ")" );
671
- }
672
-
673
- PlatformViewFactory factory = registry .getFactory (request .viewType );
674
- if (factory == null ) {
675
- throw new IllegalStateException (
676
- "Trying to create a platform view of unregistered type: " + request .viewType );
677
- }
678
-
679
- Object createParams = null ;
680
- if (request .params != null ) {
681
- createParams = factory .getCreateArgsCodec ().decodeMessage (request .params );
682
- }
683
-
684
- PlatformView platformView = factory .create (context , viewId , createParams );
685
- View view = platformView .getView ();
686
-
696
+ final View view = platformViews .get (viewId );
687
697
if (view == null ) {
688
698
throw new IllegalStateException (
689
- "PlatformView#getView() returned null, but an Android view reference was expected ." );
699
+ "Platform view hasn't been initialized from the platform view channel ." );
690
700
}
691
- if (view .getParent () != null ) {
692
- throw new IllegalStateException (
693
- "The Android view returned from PlatformView#getView() was already added to a parent view." );
701
+ if (platformViewParent .get (viewId ) != null ) {
702
+ return ;
694
703
}
695
- platformViews .put (viewId , view );
696
-
697
- FlutterMutatorView mutatorView =
704
+ final FlutterMutatorView parentView =
698
705
new FlutterMutatorView (
699
706
context , context .getResources ().getDisplayMetrics ().density , androidTouchProcessor );
700
- mutatorViews .put (viewId , mutatorView );
701
- mutatorView .addView (view );
702
- ((FlutterView ) flutterView ).addView (mutatorView );
707
+ platformViewParent .put (viewId , parentView );
708
+ parentView .addView (view );
709
+ ((FlutterView ) flutterView ).addView (parentView );
703
710
}
704
711
705
712
public void attachToFlutterRenderer (FlutterRenderer flutterRenderer ) {
@@ -718,13 +725,14 @@ public void onDisplayPlatformView(
718
725
initializeRootImageViewIfNeeded ();
719
726
initializePlatformViewIfNeeded (viewId );
720
727
721
- FlutterMutatorView mutatorView = mutatorViews .get (viewId );
722
- mutatorView .readyToDisplay (mutatorsStack , x , y , width , height );
723
- mutatorView .setVisibility (View .VISIBLE );
724
- mutatorView .bringToFront ();
728
+ final FlutterMutatorView parentView = platformViewParent .get (viewId );
729
+ parentView .readyToDisplay (mutatorsStack , x , y , width , height );
730
+ parentView .setVisibility (View .VISIBLE );
731
+ parentView .bringToFront ();
725
732
726
- FrameLayout .LayoutParams layoutParams = new FrameLayout .LayoutParams (viewWidth , viewHeight );
727
- View platformView = platformViews .get (viewId );
733
+ final FrameLayout .LayoutParams layoutParams =
734
+ new FrameLayout .LayoutParams (viewWidth , viewHeight );
735
+ final View platformView = platformViews .get (viewId );
728
736
platformView .setLayoutParams (layoutParams );
729
737
platformView .bringToFront ();
730
738
currentFrameUsedPlatformViewIds .add (viewId );
@@ -733,7 +741,7 @@ public void onDisplayPlatformView(
733
741
public void onDisplayOverlaySurface (int id , int x , int y , int width , int height ) {
734
742
initializeRootImageViewIfNeeded ();
735
743
736
- FlutterImageView overlayView = overlayLayerViews .get (id );
744
+ final FlutterImageView overlayView = overlayLayerViews .get (id );
737
745
if (overlayView .getParent () == null ) {
738
746
((FlutterView ) flutterView ).addView (overlayView );
739
747
}
@@ -776,19 +784,19 @@ public void onEndFrame() {
776
784
// If one of the surfaces doesn't have an image, the frame may be incomplete and must be
777
785
// dropped.
778
786
// For example, a toolbar widget painted by Flutter may not be rendered.
779
- boolean isFrameRenderedUsingImageReaders =
787
+ final boolean isFrameRenderedUsingImageReaders =
780
788
flutterViewConvertedToImageView && view .acquireLatestImageViewFrame ();
781
789
finishFrame (isFrameRenderedUsingImageReaders );
782
790
}
783
791
784
792
private void finishFrame (boolean isFrameRenderedUsingImageReaders ) {
785
793
for (int i = 0 ; i < overlayLayerViews .size (); i ++) {
786
- int overlayId = overlayLayerViews .keyAt (i );
787
- FlutterImageView overlayView = overlayLayerViews .valueAt (i );
794
+ final int overlayId = overlayLayerViews .keyAt (i );
795
+ final FlutterImageView overlayView = overlayLayerViews .valueAt (i );
788
796
789
797
if (currentFrameUsedOverlayLayerIds .contains (overlayId )) {
790
798
((FlutterView ) flutterView ).attachOverlaySurfaceToRender (overlayView );
791
- boolean didAcquireOverlaySurfaceImage = overlayView .acquireLatestImage ();
799
+ final boolean didAcquireOverlaySurfaceImage = overlayView .acquireLatestImage ();
792
800
isFrameRenderedUsingImageReaders &= didAcquireOverlaySurfaceImage ;
793
801
} else {
794
802
// If the background surface isn't rendered by the image view, then the
@@ -802,22 +810,20 @@ private void finishFrame(boolean isFrameRenderedUsingImageReaders) {
802
810
}
803
811
}
804
812
805
- for (int i = 0 ; i < platformViews .size (); i ++) {
806
- int viewId = platformViews .keyAt (i );
807
- View platformView = platformViews .get (viewId );
808
- View mutatorView = mutatorViews .get (viewId );
813
+ for (int i = 0 ; i < platformViewParent .size (); i ++) {
814
+ final int viewId = platformViewParent .keyAt (i );
815
+ final View parentView = platformViewParent .get (viewId );
809
816
810
817
// Show platform views only if the surfaces have images available in this frame,
811
818
// and if the platform view is rendered in this frame.
819
+ // The platform view is appended to a mutator view.
812
820
//
813
821
// Otherwise, hide the platform view, but don't remove it from the view hierarchy yet as
814
822
// they are removed when the framework diposes the platform view widget.
815
823
if (isFrameRenderedUsingImageReaders && currentFrameUsedPlatformViewIds .contains (viewId )) {
816
- platformView .setVisibility (View .VISIBLE );
817
- mutatorView .setVisibility (View .VISIBLE );
824
+ parentView .setVisibility (View .VISIBLE );
818
825
} else {
819
- platformView .setVisibility (View .GONE );
820
- mutatorView .setVisibility (View .GONE );
826
+ parentView .setVisibility (View .GONE );
821
827
}
822
828
}
823
829
}
0 commit comments