Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
Classes | Public Member Functions | Protected Member Functions | Package Attributes | List of all members
io.flutter.embedding.android.FlutterView Class Reference
Inheritance diagram for io.flutter.embedding.android.FlutterView:
io.flutter.embedding.android.KeyboardManager.ViewDelegate

Public Member Functions

 FlutterView (@NonNull Context context)
 
 FlutterView (@NonNull Context context, @NonNull RenderMode renderMode)
 
 FlutterView (@NonNull Context context, @NonNull TransparencyMode transparencyMode)
 
 FlutterView (@NonNull Context context, @NonNull FlutterSurfaceView flutterSurfaceView)
 
 FlutterView (@NonNull Context context, @NonNull FlutterTextureView flutterTextureView)
 
 FlutterView (@NonNull Context context, @NonNull FlutterImageView flutterImageView)
 
 FlutterView (@NonNull Context context, @Nullable AttributeSet attrs)
 
 FlutterView ( @NonNull Context context, @NonNull RenderMode renderMode, @NonNull TransparencyMode transparencyMode)
 
boolean hasRenderedFirstFrame ()
 
void addOnFirstFrameRenderedListener (@NonNull FlutterUiDisplayListener listener)
 
void removeOnFirstFrameRenderedListener (@NonNull FlutterUiDisplayListener listener)
 
final WindowInsets onApplyWindowInsets (@NonNull WindowInsets insets)
 
InputConnection onCreateInputConnection (@NonNull EditorInfo outAttrs)
 
boolean checkInputConnectionProxy (View view)
 
boolean dispatchKeyEvent (@NonNull KeyEvent event)
 
boolean onTouchEvent (@NonNull MotionEvent event)
 
boolean onGenericMotionEvent (@NonNull MotionEvent event)
 
boolean onHoverEvent (@NonNull MotionEvent event)
 
AccessibilityNodeProvider getAccessibilityNodeProvider ()
 
View findViewByAccessibilityIdTraversal (int accessibilityId)
 
PointerIcon getSystemPointerIcon (int type)
 
BinaryMessenger getBinaryMessenger ()
 
boolean onTextInputKeyEvent (@NonNull KeyEvent keyEvent)
 
void redispatch (@NonNull KeyEvent keyEvent)
 
void attachToFlutterEngine (@NonNull FlutterEngine flutterEngine)
 
void detachFromFlutterEngine ()
 
FlutterImageView createImageView ()
 
FlutterImageView getCurrentImageSurface ()
 
void convertToImageView ()
 
void revertImageView (@NonNull Runnable onDone)
 
void attachOverlaySurfaceToRender (@NonNull FlutterImageView view)
 
boolean acquireLatestImageViewFrame ()
 

Protected Member Functions

void onConfigurationChanged (@NonNull Configuration newConfig)
 
void onSizeChanged (int width, int height, int oldWidth, int oldHeight)
 
WindowInfoRepositoryCallbackAdapterWrapper createWindowInfoRepo ()
 
void onAttachedToWindow ()
 
void onDetachedFromWindow ()
 
void setWindowInfoListenerDisplayFeatures (WindowLayoutInfo layoutInfo)
 

Package Attributes

RenderSurface renderSurface
 

Detailed Description

Displays a Flutter UI on an Android device.

A FlutterView's UI is painted by a corresponding io.flutter.embedding.engine.FlutterEngine.

A FlutterView can operate in 2 different io.flutter.embedding.android.RenderModes:

  1. io.flutter.embedding.android.RenderMode#surface, which paints a Flutter UI to a android.view.SurfaceView. This mode has the best performance, but a
    FlutterView
    in this mode cannot be positioned between 2 other Android Views in the z-index, nor can it be animated/transformed. Unless the special capabilities of a android.graphics.SurfaceTexture are required, developers should strongly prefer this render mode.
  2. io.flutter.embedding.android.RenderMode#texture, which paints a Flutter UI to a android.graphics.SurfaceTexture. This mode is not as performant as io.flutter.embedding.android.RenderMode#surface, but a FlutterView in this mode can be animated and transformed, as well as positioned in the z-index between 2+ other Android Views. Unless the special capabilities of a android.graphics.SurfaceTexture are required, developers should strongly prefer the io.flutter.embedding.android.RenderMode#surface render mode.

See https://source.android.com/devices/graphics/arch-tv#surface_or_texture for more information comparing android.view.SurfaceView and android.view.TextureView.

Definition at line 107 of file FlutterView.java.

Constructor & Destructor Documentation

◆ FlutterView() [1/8]

io.flutter.embedding.android.FlutterView.FlutterView ( @NonNull Context  context)
inline

Constructs a FlutterView programmatically, without any XML attributes.

FlutterView requires an Activity instead of a generic Context to be compatible with PlatformViewsController.

Definition at line 217 of file FlutterView.java.

217 {
218 this(context, null, new FlutterSurfaceView(context));
219 }

◆ FlutterView() [2/8]

io.flutter.embedding.android.FlutterView.FlutterView ( @NonNull Context  context,
@NonNull RenderMode  renderMode 
)
inline

Deprecated - use FlutterView(Context, FlutterSurfaceView) or FlutterView(Context, FlutterTextureView) or FlutterView(Context, FlutterImageView) instead.

Definition at line 227 of file FlutterView.java.

227 {
228 super(context, null);
229
230 if (renderMode == RenderMode.surface) {
231 flutterSurfaceView = new FlutterSurfaceView(context);
232 renderSurface = flutterSurfaceView;
233 } else if (renderMode == RenderMode.texture) {
234 flutterTextureView = new FlutterTextureView(context);
235 renderSurface = flutterTextureView;
236 } else {
237 throw new IllegalArgumentException(
238 "RenderMode not supported with this constructor: " + renderMode);
239 }
240
241 init();
242 }

◆ FlutterView() [3/8]

io.flutter.embedding.android.FlutterView.FlutterView ( @NonNull Context  context,
@NonNull TransparencyMode  transparencyMode 
)
inline

Deprecated - use FlutterView(Context, FlutterSurfaceView) or FlutterView(Context, FlutterTextureView) instead, and configure the incoming
FlutterSurfaceView
or FlutterTextureView for transparency as desired.

Constructs a FlutterView programmatically, without any XML attributes, uses a FlutterSurfaceView to render the Flutter UI, and allows selection of a
transparencyMode
.

FlutterView requires an Activity instead of a generic Context to be compatible with PlatformViewsController.

Definition at line 257 of file FlutterView.java.

257 {
258 this(
259 context,
260 null,
261 new FlutterSurfaceView(context, transparencyMode == TransparencyMode.transparent));
262 }

◆ FlutterView() [4/8]

io.flutter.embedding.android.FlutterView.FlutterView ( @NonNull Context  context,
@NonNull FlutterSurfaceView  flutterSurfaceView 
)
inline

Constructs a FlutterView programmatically, without any XML attributes, uses the given FlutterSurfaceView to render the Flutter UI, and allows selection of a
transparencyMode
.

FlutterView requires an Activity instead of a generic Context to be compatible with PlatformViewsController.

Definition at line 272 of file FlutterView.java.

272 {
273 this(context, null, flutterSurfaceView);
274 }

◆ FlutterView() [5/8]

io.flutter.embedding.android.FlutterView.FlutterView ( @NonNull Context  context,
@NonNull FlutterTextureView  flutterTextureView 
)
inline

Constructs a FlutterView programmatically, without any XML attributes, uses the given FlutterTextureView to render the Flutter UI, and allows selection of a
transparencyMode
.

FlutterView requires an Activity instead of a generic Context to be compatible with PlatformViewsController.

Definition at line 284 of file FlutterView.java.

284 {
285 this(context, null, flutterTextureView);
286 }

◆ FlutterView() [6/8]

io.flutter.embedding.android.FlutterView.FlutterView ( @NonNull Context  context,
@NonNull FlutterImageView  flutterImageView 
)
inline

Constructs a FlutterView programmatically, without any XML attributes, uses the given FlutterImageView to render the Flutter UI.

FlutterView requires an Activity instead of a generic Context to be compatible with PlatformViewsController.

Definition at line 295 of file FlutterView.java.

295 {
296 this(context, null, flutterImageView);
297 }

◆ FlutterView() [7/8]

io.flutter.embedding.android.FlutterView.FlutterView ( @NonNull Context  context,
@Nullable AttributeSet  attrs 
)
inline

Constructs a FlutterView in an XML-inflation-compliant manner.

FlutterView requires an Activity instead of a generic Context to be compatible with PlatformViewsController.

Definition at line 306 of file FlutterView.java.

306 {
307 this(context, attrs, new FlutterSurfaceView(context));
308 }

◆ FlutterView() [8/8]

io.flutter.embedding.android.FlutterView.FlutterView ( @NonNull Context  context,
@NonNull RenderMode  renderMode,
@NonNull TransparencyMode  transparencyMode 
)
inline

Deprecated - use FlutterView(Context, FlutterSurfaceView) or FlutterView(Context, FlutterTextureView) instead, and configure the incoming
FlutterSurfaceView
or FlutterTextureView for transparency as desired.

Definition at line 316 of file FlutterView.java.

319 {
320 super(context, null);
321
322 if (renderMode == RenderMode.surface) {
323 flutterSurfaceView =
324 new FlutterSurfaceView(context, transparencyMode == TransparencyMode.transparent);
325 renderSurface = flutterSurfaceView;
326 } else if (renderMode == RenderMode.texture) {
327 flutterTextureView = new FlutterTextureView(context);
328 renderSurface = flutterTextureView;
329 } else {
330 throw new IllegalArgumentException(
331 "RenderMode not supported with this constructor: " + renderMode);
332 }
333
334 init();
335 }

Member Function Documentation

◆ acquireLatestImageViewFrame()

boolean io.flutter.embedding.android.FlutterView.acquireLatestImageViewFrame ( )
inline

Definition at line 1347 of file FlutterView.java.

1347 {
1348 if (flutterImageView != null) {
1349 return flutterImageView.acquireLatestImage();
1350 }
1351 return false;
1352 }

◆ addOnFirstFrameRenderedListener()

void io.flutter.embedding.android.FlutterView.addOnFirstFrameRenderedListener ( @NonNull FlutterUiDisplayListener  listener)
inline

Adds the given listener to this FlutterView, to be notified upon Flutter's first rendered frame.

Definition at line 420 of file FlutterView.java.

420 {
421 flutterUiDisplayListeners.add(listener);
422 }

◆ attachOverlaySurfaceToRender()

void io.flutter.embedding.android.FlutterView.attachOverlaySurfaceToRender ( @NonNull FlutterImageView  view)
inline

Definition at line 1341 of file FlutterView.java.

1341 {
1342 if (flutterEngine != null) {
1343 view.attachToRenderer(flutterEngine.getRenderer());
1344 }
1345 }

◆ attachToFlutterEngine()

void io.flutter.embedding.android.FlutterView.attachToFlutterEngine ( @NonNull FlutterEngine  flutterEngine)
inline

Connects this FlutterView to the given io.flutter.embedding.engine.FlutterEngine.

This FlutterView will begin rendering the UI painted by the given FlutterEngine. This FlutterView will also begin forwarding interaction events from this FlutterView to the given io.flutter.embedding.engine.FlutterEngine, e.g., user touch events, accessibility events, keyboard events, and others.

See detachFromFlutterEngine() for information on how to detach from a FlutterEngine.

Definition at line 1076 of file FlutterView.java.

1076 {
1077 Log.v(TAG, "Attaching to a FlutterEngine: " + flutterEngine);
1078 if (isAttachedToFlutterEngine()) {
1079 if (flutterEngine == this.flutterEngine) {
1080 // We are already attached to this FlutterEngine
1081 Log.v(TAG, "Already attached to this engine. Doing nothing.");
1082 return;
1083 }
1084
1085 // Detach from a previous FlutterEngine so we can attach to this new one.
1086 Log.v(
1087 TAG,
1088 "Currently attached to a different engine. Detaching and then attaching"
1089 + " to new engine.");
1091 }
1092
1093 this.flutterEngine = flutterEngine;
1094
1095 // Instruct our FlutterRenderer that we are now its designated RenderSurface.
1096 FlutterRenderer flutterRenderer = this.flutterEngine.getRenderer();
1097 isFlutterUiDisplayed = flutterRenderer.isDisplayingFlutterUi();
1098 renderSurface.attachToRenderer(flutterRenderer);
1099 flutterRenderer.addIsDisplayingFlutterUiListener(flutterUiDisplayListener);
1100
1101 // Initialize various components that know how to process Android View I/O
1102 // in a way that Flutter understands.
1103 if (Build.VERSION.SDK_INT >= API_LEVELS.API_24) {
1104 mouseCursorPlugin = new MouseCursorPlugin(this, this.flutterEngine.getMouseCursorChannel());
1105 }
1106 textInputPlugin =
1107 new TextInputPlugin(
1108 this,
1109 this.flutterEngine.getTextInputChannel(),
1110 this.flutterEngine.getPlatformViewsController());
1111
1112 try {
1113 textServicesManager =
1114 (TextServicesManager)
1115 getContext().getSystemService(Context.TEXT_SERVICES_MANAGER_SERVICE);
1116 spellCheckPlugin =
1117 new SpellCheckPlugin(textServicesManager, this.flutterEngine.getSpellCheckChannel());
1118 } catch (Exception e) {
1119 Log.e(TAG, "TextServicesManager not supported by device, spell check disabled.");
1120 }
1121
1122 localizationPlugin = this.flutterEngine.getLocalizationPlugin();
1123
1124 keyboardManager = new KeyboardManager(this);
1125 androidTouchProcessor =
1126 new AndroidTouchProcessor(this.flutterEngine.getRenderer(), /*trackMotionEvents=*/ false);
1127 accessibilityBridge =
1128 new AccessibilityBridge(
1129 this,
1130 flutterEngine.getAccessibilityChannel(),
1131 (AccessibilityManager) getContext().getSystemService(Context.ACCESSIBILITY_SERVICE),
1132 getContext().getContentResolver(),
1133 this.flutterEngine.getPlatformViewsController());
1134 accessibilityBridge.setOnAccessibilityChangeListener(onAccessibilityChangeListener);
1135 resetWillNotDraw(
1136 accessibilityBridge.isAccessibilityEnabled(),
1137 accessibilityBridge.isTouchExplorationEnabled());
1138
1139 // Connect AccessibilityBridge to the PlatformViewsController within the FlutterEngine.
1140 // This allows platform Views to hook into Flutter's overall accessibility system.
1141 this.flutterEngine.getPlatformViewsController().attachAccessibilityBridge(accessibilityBridge);
1142 this.flutterEngine
1143 .getPlatformViewsController()
1144 .attachToFlutterRenderer(this.flutterEngine.getRenderer());
1145
1146 // Inform the Android framework that it should retrieve a new InputConnection
1147 // now that an engine is attached.
1148 // TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin
1149 textInputPlugin.getInputMethodManager().restartInput(this);
1150
1151 // Push View and Context related information from Android to Flutter.
1152 sendUserSettingsToFlutter();
1153 getContext()
1154 .getContentResolver()
1155 .registerContentObserver(
1156 Settings.System.getUriFor(Settings.System.TEXT_SHOW_PASSWORD),
1157 false,
1158 systemSettingsObserver);
1159
1160 sendViewportMetricsToFlutter();
1161
1162 flutterEngine.getPlatformViewsController().attachToView(this);
1163
1164 // Notify engine attachment listeners of the attachment.
1165 for (FlutterEngineAttachmentListener listener : flutterEngineAttachmentListeners) {
1166 listener.onFlutterEngineAttachedToFlutterView(flutterEngine);
1167 }
1168
1169 // If the first frame has already been rendered, notify all first frame listeners.
1170 // Do this after all other initialization so that listeners don't inadvertently interact
1171 // with a FlutterView that is only partially attached to a FlutterEngine.
1172 if (isFlutterUiDisplayed) {
1173 flutterUiDisplayListener.onFlutterUiDisplayed();
1174 }
1175 }
void Log(const char *format,...) SK_PRINTF_LIKE(1
Build(configs, env, options)
Definition build.py:232

◆ checkInputConnectionProxy()

boolean io.flutter.embedding.android.FlutterView.checkInputConnectionProxy ( View  view)
inline

Allows a View that is not currently the input connection target to invoke commands on the android.view.inputmethod.InputMethodManager, which is otherwise disallowed.

Returns true to allow non-input-connection-targets to invoke methods on
InputMethodManager
, or false to exclusively allow the input connection target to invoke such methods.

Definition at line 838 of file FlutterView.java.

838 {
839 return flutterEngine != null
840 ? flutterEngine.getPlatformViewsController().checkInputConnectionProxy(view)
841 : super.checkInputConnectionProxy(view);
842 }

◆ convertToImageView()

void io.flutter.embedding.android.FlutterView.convertToImageView ( )
inline

Converts the current render surface to a FlutterImageView if it's not one already. Otherwise, it resizes the FlutterImageView based on the current view size.

Definition at line 1272 of file FlutterView.java.

1272 {
1273 renderSurface.pause();
1274
1275 if (flutterImageView == null) {
1276 flutterImageView = createImageView();
1277 addView(flutterImageView);
1278 } else {
1279 flutterImageView.resizeIfNeeded(getWidth(), getHeight());
1280 }
1281
1282 previousRenderSurface = renderSurface;
1283 renderSurface = flutterImageView;
1284 if (flutterEngine != null) {
1285 renderSurface.attachToRenderer(flutterEngine.getRenderer());
1286 }
1287 }
void attachToRenderer(@NonNull FlutterRenderer flutterRenderer)

◆ createImageView()

FlutterImageView io.flutter.embedding.android.FlutterView.createImageView ( )
inline

Definition at line 1258 of file FlutterView.java.

1258 {
1259 return new FlutterImageView(
1260 getContext(), getWidth(), getHeight(), FlutterImageView.SurfaceKind.background);
1261 }

◆ createWindowInfoRepo()

WindowInfoRepositoryCallbackAdapterWrapper io.flutter.embedding.android.FlutterView.createWindowInfoRepo ( )
inlineprotected

Definition at line 487 of file FlutterView.java.

487 {
488 try {
489 return new WindowInfoRepositoryCallbackAdapterWrapper(
490 new WindowInfoTrackerCallbackAdapter(
491 WindowInfoTracker.Companion.getOrCreate(getContext())));
492 } catch (NoClassDefFoundError noClassDefFoundError) {
493 // Testing environment uses gn/javac, which does not work with aar files. This is why aar
494 // are converted to jar files, losing resources and other android-specific files.
495 // androidx.window does contain resources, which causes it to fail during testing, since the
496 // class androidx.window.R is not found.
497 // This method is mocked in the tests involving androidx.window, but this catch block is
498 // needed for other tests, which would otherwise fail during onAttachedToWindow().
499 return null;
500 }
501 }

◆ detachFromFlutterEngine()

void io.flutter.embedding.android.FlutterView.detachFromFlutterEngine ( )
inline

Disconnects this FlutterView from a previously attached io.flutter.embedding.engine.FlutterEngine.

This FlutterView will clear its UI and stop forwarding all events to the previously-attached io.flutter.embedding.engine.FlutterEngine. This includes touch events, accessibility events, keyboard events, and others.

See attachToFlutterEngine(FlutterEngine) for information on how to attach a FlutterEngine.

Definition at line 1188 of file FlutterView.java.

1188 {
1189 Log.v(TAG, "Detaching from a FlutterEngine: " + flutterEngine);
1190 if (!isAttachedToFlutterEngine()) {
1191 Log.v(TAG, "FlutterView not attached to an engine. Not detaching.");
1192 return;
1193 }
1194
1195 // Notify engine attachment listeners of the detachment.
1196 for (FlutterEngineAttachmentListener listener : flutterEngineAttachmentListeners) {
1197 listener.onFlutterEngineDetachedFromFlutterView();
1198 }
1199
1200 getContext().getContentResolver().unregisterContentObserver(systemSettingsObserver);
1201
1202 flutterEngine.getPlatformViewsController().detachFromView();
1203
1204 // Disconnect the FlutterEngine's PlatformViewsController from the AccessibilityBridge.
1205 flutterEngine.getPlatformViewsController().detachAccessibilityBridge();
1206
1207 // Disconnect and clean up the AccessibilityBridge.
1208 accessibilityBridge.release();
1209 accessibilityBridge = null;
1210
1211 // Inform the Android framework that it should retrieve a new InputConnection
1212 // now that the engine is detached. The new InputConnection will be null, which
1213 // signifies that this View does not process input (until a new engine is attached).
1214 // TODO(mattcarroll): once this is proven to work, move this line ot TextInputPlugin
1215 textInputPlugin.getInputMethodManager().restartInput(this);
1216 textInputPlugin.destroy();
1217 keyboardManager.destroy();
1218 if (spellCheckPlugin != null) {
1219 spellCheckPlugin.destroy();
1220 }
1221
1222 if (mouseCursorPlugin != null) {
1223 mouseCursorPlugin.destroy();
1224 }
1225
1226 // Instruct our FlutterRenderer that we are no longer interested in being its RenderSurface.
1227 FlutterRenderer flutterRenderer = flutterEngine.getRenderer();
1228 isFlutterUiDisplayed = false;
1229 flutterRenderer.removeIsDisplayingFlutterUiListener(flutterUiDisplayListener);
1230 flutterRenderer.stopRenderingToSurface();
1231 flutterRenderer.setSemanticsEnabled(false);
1232
1233 // Revert the image view to previous surface
1234 if (previousRenderSurface != null && renderSurface == flutterImageView) {
1235 renderSurface = previousRenderSurface;
1236 }
1237 renderSurface.detachFromRenderer();
1238
1239 releaseImageView();
1240
1241 previousRenderSurface = null;
1242 flutterEngine = null;
1243 }

◆ dispatchKeyEvent()

boolean io.flutter.embedding.android.FlutterView.dispatchKeyEvent ( @NonNull KeyEvent  event)
inline

Invoked when a hardware key is pressed or released.

This method is typically invoked in response to the press of a physical keyboard key or a D-pad button. It is generally not invoked when a virtual software keyboard is used, though a software keyboard may choose to invoke this method in some situations.

KeyEvents are sent from Android to Flutter. KeyboardManager may do some additional work with the given KeyEvent, e.g., combine this keyCode with the previous keyCode to generate a unicode combined character.

Definition at line 856 of file FlutterView.java.

856 {
857 if (event.getAction() == KeyEvent.ACTION_DOWN && event.getRepeatCount() == 0) {
858 // Tell Android to start tracking this event.
859 getKeyDispatcherState().startTracking(event, this);
860 } else if (event.getAction() == KeyEvent.ACTION_UP) {
861 // Stop tracking the event.
862 getKeyDispatcherState().handleUpEvent(event);
863 }
864 // If the key processor doesn't handle it, then send it on to the
865 // superclass. The key processor will typically handle all events except
866 // those where it has re-dispatched the event after receiving a reply from
867 // the framework that the framework did not handle it.
868 return (isAttachedToFlutterEngine() && keyboardManager.handleEvent(event))
869 || super.dispatchKeyEvent(event);
870 }
boolean handleEvent(@NonNull KeyEvent keyEvent)
FlKeyEvent * event

◆ findViewByAccessibilityIdTraversal()

View io.flutter.embedding.android.FlutterView.findViewByAccessibilityIdTraversal ( int  accessibilityId)
inline

Prior to Android Q, it's impossible to add real views as descendants of virtual nodes. This breaks accessibility when an Android view is embedded in a Flutter app.

This method overrides a hidden method in ViewGroup to workaround this limitation. This solution is derivated from Jetpack Compose, and can be found in the Android source code as well.

This workaround finds the descendant View that matches the provided accessibility id.

Parameters
accessibilityIdThe view accessibility id.
Returns
The view matching the accessibility id if any.

Definition at line 960 of file FlutterView.java.

960 {
961 if (Build.VERSION.SDK_INT < API_LEVELS.API_29) {
962 return findViewByAccessibilityIdRootedAtCurrentView(accessibilityId, this);
963 }
964 // Android Q or later doesn't call this method.
965 //
966 // However, since this is implementation detail, a future version of Android might call
967 // this method again, fallback to calling the This member is not intended for public use, and is
968 // only visible for testing. method as expected by ViewGroup.
969 Method findViewByAccessibilityIdTraversalMethod;
970 try {
971 findViewByAccessibilityIdTraversalMethod =
972 View.class.getDeclaredMethod("findViewByAccessibilityIdTraversal", int.class);
973 } catch (NoSuchMethodException exception) {
974 return null;
975 }
976 findViewByAccessibilityIdTraversalMethod.setAccessible(true);
977 try {
978 return (View) findViewByAccessibilityIdTraversalMethod.invoke(this, accessibilityId);
979 } catch (IllegalAccessException exception) {
980 return null;
981 } catch (InvocationTargetException exception) {
982 return null;
983 }
984 }

◆ getAccessibilityNodeProvider()

AccessibilityNodeProvider io.flutter.embedding.android.FlutterView.getAccessibilityNodeProvider ( )
inline

Definition at line 933 of file FlutterView.java.

933 {
934 if (accessibilityBridge != null && accessibilityBridge.isAccessibilityEnabled()) {
935 return accessibilityBridge;
936 } else {
937 // TODO(goderbauer): when a11y is off this should return a one-off snapshot of
938 // the a11y
939 // tree.
940 return null;
941 }
942 }

◆ getBinaryMessenger()

BinaryMessenger io.flutter.embedding.android.FlutterView.getBinaryMessenger ( )
inline

Returns a BinaryMessenger to send platform messages with.

Implements io.flutter.embedding.android.KeyboardManager.ViewDelegate.

Definition at line 1048 of file FlutterView.java.

1048 {
1049 return flutterEngine.getDartExecutor();
1050 }

◆ getCurrentImageSurface()

FlutterImageView io.flutter.embedding.android.FlutterView.getCurrentImageSurface ( )
inline

Definition at line 1264 of file FlutterView.java.

1264 {
1265 return flutterImageView;
1266 }

◆ getSystemPointerIcon()

PointerIcon io.flutter.embedding.android.FlutterView.getSystemPointerIcon ( int  type)
inline

Definition at line 1040 of file FlutterView.java.

1040 {
1041 return PointerIcon.getSystemIcon(getContext(), type);
1042 }

◆ hasRenderedFirstFrame()

boolean io.flutter.embedding.android.FlutterView.hasRenderedFirstFrame ( )
inline

Returns true if an attached io.flutter.embedding.engine.FlutterEngine has rendered at least 1 frame to this FlutterView.

Returns false if no io.flutter.embedding.engine.FlutterEngine is attached.

This flag is specific to a given io.flutter.embedding.engine.FlutterEngine. The following hypothetical timeline demonstrates how this flag changes over time.

  1. flutterEngineA is attached to this FlutterView: returns false
  2. flutterEngineA renders its first frame to this FlutterView: returns true
  3. flutterEngineA is detached from this FlutterView: returns false
  4. flutterEngineB is attached to this FlutterView: returns false
  5. flutterEngineB renders its first frame to this FlutterView: returns true

Definition at line 412 of file FlutterView.java.

412 {
413 return isFlutterUiDisplayed;
414 }

◆ onApplyWindowInsets()

final WindowInsets io.flutter.embedding.android.FlutterView.onApplyWindowInsets ( @NonNull WindowInsets  insets)
inline

Invoked when Android's desired window insets change, i.e., padding.

Flutter does not use a standard View hierarchy and therefore Flutter is unaware of these insets. Therefore, this method calculates the viewport metrics that Flutter should use and then sends those metrics to Flutter.

This callback is not present in API < 20, which means lower API devices will see the wider than expected padding when the status and navigation bars are hidden.

Definition at line 678 of file FlutterView.java.

678 {
679 WindowInsets newInsets = super.onApplyWindowInsets(insets);
680
681 // getSystemGestureInsets() was introduced in API 29 and immediately deprecated in 30.
682 if (Build.VERSION.SDK_INT == API_LEVELS.API_29) {
683 Insets systemGestureInsets = insets.getSystemGestureInsets();
684 viewportMetrics.systemGestureInsetTop = systemGestureInsets.top;
685 viewportMetrics.systemGestureInsetRight = systemGestureInsets.right;
686 viewportMetrics.systemGestureInsetBottom = systemGestureInsets.bottom;
687 viewportMetrics.systemGestureInsetLeft = systemGestureInsets.left;
688 }
689
690 boolean statusBarVisible = (SYSTEM_UI_FLAG_FULLSCREEN & getWindowSystemUiVisibility()) == 0;
691 boolean navigationBarVisible =
692 (SYSTEM_UI_FLAG_HIDE_NAVIGATION & getWindowSystemUiVisibility()) == 0;
693
694 if (Build.VERSION.SDK_INT >= API_LEVELS.API_30) {
695 int mask = 0;
696 if (navigationBarVisible) {
697 mask = mask | android.view.WindowInsets.Type.navigationBars();
698 }
699 if (statusBarVisible) {
700 mask = mask | android.view.WindowInsets.Type.statusBars();
701 }
702 Insets uiInsets = insets.getInsets(mask);
703 viewportMetrics.viewPaddingTop = uiInsets.top;
704 viewportMetrics.viewPaddingRight = uiInsets.right;
705 viewportMetrics.viewPaddingBottom = uiInsets.bottom;
706 viewportMetrics.viewPaddingLeft = uiInsets.left;
707
708 Insets imeInsets = insets.getInsets(android.view.WindowInsets.Type.ime());
709 viewportMetrics.viewInsetTop = imeInsets.top;
710 viewportMetrics.viewInsetRight = imeInsets.right;
711 viewportMetrics.viewInsetBottom = imeInsets.bottom; // Typically, only bottom is non-zero
712 viewportMetrics.viewInsetLeft = imeInsets.left;
713
714 Insets systemGestureInsets =
715 insets.getInsets(android.view.WindowInsets.Type.systemGestures());
716 viewportMetrics.systemGestureInsetTop = systemGestureInsets.top;
717 viewportMetrics.systemGestureInsetRight = systemGestureInsets.right;
718 viewportMetrics.systemGestureInsetBottom = systemGestureInsets.bottom;
719 viewportMetrics.systemGestureInsetLeft = systemGestureInsets.left;
720
721 // TODO(garyq): Expose the full rects of the display cutout.
722
723 // Take the max of the display cutout insets and existing padding to merge them
724 DisplayCutout cutout = insets.getDisplayCutout();
725 if (cutout != null) {
726 Insets waterfallInsets = cutout.getWaterfallInsets();
727 viewportMetrics.viewPaddingTop =
728 Math.max(
729 Math.max(viewportMetrics.viewPaddingTop, waterfallInsets.top),
730 cutout.getSafeInsetTop());
731 viewportMetrics.viewPaddingRight =
732 Math.max(
733 Math.max(viewportMetrics.viewPaddingRight, waterfallInsets.right),
734 cutout.getSafeInsetRight());
735 viewportMetrics.viewPaddingBottom =
736 Math.max(
737 Math.max(viewportMetrics.viewPaddingBottom, waterfallInsets.bottom),
738 cutout.getSafeInsetBottom());
739 viewportMetrics.viewPaddingLeft =
740 Math.max(
741 Math.max(viewportMetrics.viewPaddingLeft, waterfallInsets.left),
742 cutout.getSafeInsetLeft());
743 }
744 } else {
745 // We zero the left and/or right sides to prevent the padding the
746 // navigation bar would have caused.
747 ZeroSides zeroSides = ZeroSides.NONE;
748 if (!navigationBarVisible) {
749 zeroSides = calculateShouldZeroSides();
750 }
751
752 // Status bar (top), navigation bar (bottom) and left/right system insets should
753 // partially obscure the content (padding).
754 viewportMetrics.viewPaddingTop = statusBarVisible ? insets.getSystemWindowInsetTop() : 0;
755 viewportMetrics.viewPaddingRight =
756 zeroSides == ZeroSides.RIGHT || zeroSides == ZeroSides.BOTH
757 ? 0
758 : insets.getSystemWindowInsetRight();
759 viewportMetrics.viewPaddingBottom =
760 navigationBarVisible && guessBottomKeyboardInset(insets) == 0
761 ? insets.getSystemWindowInsetBottom()
762 : 0;
763 viewportMetrics.viewPaddingLeft =
764 zeroSides == ZeroSides.LEFT || zeroSides == ZeroSides.BOTH
765 ? 0
766 : insets.getSystemWindowInsetLeft();
767
768 // Bottom system inset (keyboard) should adjust scrollable bottom edge (inset).
769 viewportMetrics.viewInsetTop = 0;
770 viewportMetrics.viewInsetRight = 0;
771 viewportMetrics.viewInsetBottom = guessBottomKeyboardInset(insets);
772 viewportMetrics.viewInsetLeft = 0;
773 }
774
775 Log.v(
776 TAG,
777 "Updating window insets (onApplyWindowInsets()):\n"
778 + "Status bar insets: Top: "
779 + viewportMetrics.viewPaddingTop
780 + ", Left: "
781 + viewportMetrics.viewPaddingLeft
782 + ", Right: "
783 + viewportMetrics.viewPaddingRight
784 + "\n"
785 + "Keyboard insets: Bottom: "
786 + viewportMetrics.viewInsetBottom
787 + ", Left: "
788 + viewportMetrics.viewInsetLeft
789 + ", Right: "
790 + viewportMetrics.viewInsetRight
791 + "System Gesture Insets - Left: "
792 + viewportMetrics.systemGestureInsetLeft
793 + ", Top: "
794 + viewportMetrics.systemGestureInsetTop
795 + ", Right: "
796 + viewportMetrics.systemGestureInsetRight
797 + ", Bottom: "
798 + viewportMetrics.viewInsetBottom);
799
800 sendViewportMetricsToFlutter();
801 return newInsets;
802 }

◆ onAttachedToWindow()

void io.flutter.embedding.android.FlutterView.onAttachedToWindow ( )
inlineprotected

Invoked when this is attached to the window.

We register for androidx.window.layout.WindowInfoTracker updates.

Definition at line 509 of file FlutterView.java.

509 {
510 super.onAttachedToWindow();
511 this.windowInfoRepo = createWindowInfoRepo();
512 Activity activity = ViewUtils.getActivity(getContext());
513 if (windowInfoRepo != null && activity != null) {
514 windowInfoRepo.addWindowLayoutInfoListener(
515 activity, ContextCompat.getMainExecutor(getContext()), windowInfoListener);
516 }
517 }
WindowInfoRepositoryCallbackAdapterWrapper createWindowInfoRepo()
void addWindowLayoutInfoListener( @NonNull Activity activity, @NonNull Executor executor, @NonNull Consumer< WindowLayoutInfo > consumer)

◆ onConfigurationChanged()

void io.flutter.embedding.android.FlutterView.onConfigurationChanged ( @NonNull Configuration  newConfig)
inlineprotected

Sends relevant configuration data from Android to Flutter when the Android Configuration changes.

The Android Configuration might change as a result of device orientation change, device language change, device text scale factor change, etc.

Definition at line 441 of file FlutterView.java.

441 {
442 super.onConfigurationChanged(newConfig);
443 // We've observed on Android Q that going to the background, changing
444 // orientation, and bringing the app back to foreground results in a sequence
445 // of detatch from flutterEngine, onConfigurationChanged, followed by attach
446 // to flutterEngine.
447 // No-op here so that we avoid NPE; these channels will get notified once
448 // the activity or fragment tell the view to attach to the Flutter engine
449 // again (e.g. in onStart).
450 if (flutterEngine != null) {
451 Log.v(TAG, "Configuration changed. Sending locales and user settings to Flutter.");
452 localizationPlugin.sendLocalesToFlutter(newConfig);
453 sendUserSettingsToFlutter();
454
455 ViewUtils.calculateMaximumDisplayMetrics(getContext(), flutterEngine);
456 }
457 }

◆ onCreateInputConnection()

InputConnection io.flutter.embedding.android.FlutterView.onCreateInputConnection ( @NonNull EditorInfo  outAttrs)
inline

Creates an InputConnection to work with a android.view.inputmethod.InputMethodManager.

Any View that can take focus or process text input must implement this method by returning a non-null InputConnection. Flutter may render one or many focusable and text-input widgets, therefore FlutterView must support an InputConnection.

The InputConnection returned from this method comes from a TextInputPlugin, which is owned by this FlutterView. A TextInputPlugin exists to encapsulate the nuances of input communication, rather than spread that logic throughout this
FlutterView
.

Definition at line 821 of file FlutterView.java.

821 {
822 if (!isAttachedToFlutterEngine()) {
823 return super.onCreateInputConnection(outAttrs);
824 }
825
826 return textInputPlugin.createInputConnection(this, keyboardManager, outAttrs);
827 }

◆ onDetachedFromWindow()

void io.flutter.embedding.android.FlutterView.onDetachedFromWindow ( )
inlineprotected

Invoked when this is detached from the window.

We unregister from androidx.window.layout.WindowInfoTracker updates.

Definition at line 525 of file FlutterView.java.

525 {
526 if (windowInfoRepo != null) {
527 windowInfoRepo.removeWindowLayoutInfoListener(windowInfoListener);
528 }
529 this.windowInfoRepo = null;
530 super.onDetachedFromWindow();
531 }

◆ onGenericMotionEvent()

boolean io.flutter.embedding.android.FlutterView.onGenericMotionEvent ( @NonNull MotionEvent  event)
inline

Invoked by Android when a generic motion event occurs, e.g., joystick movement, mouse hover, track pad touches, scroll wheel movements, etc.

Flutter handles all of its own gesture detection and processing, therefore this method forwards all MotionEvent data from Android to Flutter.

Definition at line 897 of file FlutterView.java.

897 {
898 boolean handled =
899 isAttachedToFlutterEngine()
900 && androidTouchProcessor.onGenericMotionEvent(event, getContext());
901 return handled ? true : super.onGenericMotionEvent(event);
902 }
boolean onGenericMotionEvent(@NonNull MotionEvent event, @NonNull Context context)

◆ onHoverEvent()

boolean io.flutter.embedding.android.FlutterView.onHoverEvent ( @NonNull MotionEvent  event)
inline

Invoked by Android when a hover-compliant input system causes a hover event.

An example of hover events is a stylus sitting near an Android screen. As the stylus moves from outside a View to hover over a View, or move around within a View, or moves from over a View to outside a View, a corresponding MotionEvent is reported via this method.

Hover events can be used for accessibility touch exploration and therefore are processed here for accessibility purposes.

Definition at line 916 of file FlutterView.java.

916 {
917 if (!isAttachedToFlutterEngine()) {
918 return super.onHoverEvent(event);
919 }
920
921 boolean handled = accessibilityBridge.onAccessibilityHoverEvent(event);
922 if (!handled) {
923 // TODO(ianh): Expose hover events to the platform,
924 // implementing ADD, REMOVE, etc.
925 }
926 return handled;
927 }

◆ onSizeChanged()

void io.flutter.embedding.android.FlutterView.onSizeChanged ( int  width,
int  height,
int  oldWidth,
int  oldHeight 
)
inlineprotected

Invoked when this FlutterView changes size, including upon initial measure.

The initial measure reports an oldWidth and oldHeight of zero.

Flutter cares about the width and height of the view that displays it on the host platform. Therefore, when this method is invoked, the new width and height are communicated to Flutter as the "physical size" of the view that displays Flutter's UI.

Definition at line 469 of file FlutterView.java.

469 {
470 super.onSizeChanged(width, height, oldWidth, oldHeight);
471 Log.v(
472 TAG,
473 "Size changed. Sending Flutter new viewport metrics. FlutterView was "
474 + oldWidth
475 + " x "
476 + oldHeight
477 + ", it is now "
478 + width
479 + " x "
480 + height);
481 viewportMetrics.width = width;
482 viewportMetrics.height = height;
483 sendViewportMetricsToFlutter();
484 }
int32_t height
int32_t width

◆ onTextInputKeyEvent()

boolean io.flutter.embedding.android.FlutterView.onTextInputKeyEvent ( @NonNull KeyEvent  keyEvent)
inline

Send a KeyEvent that is not handled by the keyboard responders to the text input system.

Parameters
keyEventthe KeyEvent that should be processed by the text input system. It must not be null.
Returns
Whether the text input handles the key event.

Implements io.flutter.embedding.android.KeyboardManager.ViewDelegate.

Definition at line 1053 of file FlutterView.java.

1053 {
1054 return textInputPlugin.handleKeyEvent(keyEvent);
1055 }

◆ onTouchEvent()

boolean io.flutter.embedding.android.FlutterView.onTouchEvent ( @NonNull MotionEvent  event)
inline

Invoked by Android when a user touch event occurs.

Flutter handles all of its own gesture detection and processing, therefore this method forwards all MotionEvent data from Android to Flutter.

Definition at line 879 of file FlutterView.java.

879 {
880 if (!isAttachedToFlutterEngine()) {
881 return super.onTouchEvent(event);
882 }
883
884 requestUnbufferedDispatch(event);
885
886 return androidTouchProcessor.onTouchEvent(event);
887 }

◆ redispatch()

void io.flutter.embedding.android.FlutterView.redispatch ( @NonNull KeyEvent  keyEvent)
inline

Send a KeyEvent that is not handled by Flutter back to the platform.

Implements io.flutter.embedding.android.KeyboardManager.ViewDelegate.

Definition at line 1058 of file FlutterView.java.

1058 {
1059 getRootView().dispatchKeyEvent(keyEvent);
1060 }

◆ removeOnFirstFrameRenderedListener()

void io.flutter.embedding.android.FlutterView.removeOnFirstFrameRenderedListener ( @NonNull FlutterUiDisplayListener  listener)
inline

Removes the given listener, which was previously added with addOnFirstFrameRenderedListener(FlutterUiDisplayListener).

Definition at line 428 of file FlutterView.java.

428 {
429 flutterUiDisplayListeners.remove(listener);
430 }

◆ revertImageView()

void io.flutter.embedding.android.FlutterView.revertImageView ( @NonNull Runnable  onDone)
inline

If the surface is rendered by a FlutterImageView, then calling this method will stop rendering to a FlutterImageView, and render on the previous surface instead.

Parameters
onDonea callback called when Flutter UI is rendered on the previous surface. Use this callback to perform cleanups. For example, destroy overlay surfaces.

Definition at line 1296 of file FlutterView.java.

1296 {
1297 if (flutterImageView == null) {
1298 Log.v(TAG, "Tried to revert the image view, but no image view is used.");
1299 return;
1300 }
1301 if (previousRenderSurface == null) {
1302 Log.v(TAG, "Tried to revert the image view, but no previous surface was used.");
1303 return;
1304 }
1305 renderSurface = previousRenderSurface;
1306 previousRenderSurface = null;
1307
1308 final FlutterRenderer renderer = flutterEngine.getRenderer();
1309
1310 if (flutterEngine == null || renderer == null) {
1311 flutterImageView.detachFromRenderer();
1312 releaseImageView();
1313 onDone.run();
1314 return;
1315 }
1316 // Resume rendering to the previous surface.
1317 // This surface is typically `FlutterSurfaceView` or `FlutterTextureView`.
1318 renderSurface.resume();
1319
1320 // Install a Flutter UI listener to wait until the first frame is rendered
1321 // in the new surface to call the `onDone` callback.
1322 renderer.addIsDisplayingFlutterUiListener(
1323 new FlutterUiDisplayListener() {
1324 @Override
1325 public void onFlutterUiDisplayed() {
1326 renderer.removeIsDisplayingFlutterUiListener(this);
1327 onDone.run();
1328 if (!(renderSurface instanceof FlutterImageView) && flutterImageView != null) {
1329 flutterImageView.detachFromRenderer();
1330 releaseImageView();
1331 }
1332 }
1333
1334 @Override
1335 public void onFlutterUiNoLongerDisplayed() {
1336 // no-op
1337 }
1338 });
1339 }

◆ setWindowInfoListenerDisplayFeatures()

void io.flutter.embedding.android.FlutterView.setWindowInfoListenerDisplayFeatures ( WindowLayoutInfo  layoutInfo)
inlineprotected

Refresh androidx.window.layout.WindowInfoTracker and android.view.DisplayCutout display features. Fold, hinge and cutout areas are populated here.

Definition at line 538 of file FlutterView.java.

538 {
539 List<DisplayFeature> displayFeatures = layoutInfo.getDisplayFeatures();
540 List<FlutterRenderer.DisplayFeature> result = new ArrayList<>();
541
542 // Data from WindowInfoTracker display features. Fold and hinge areas are
543 // populated here.
544 for (DisplayFeature displayFeature : displayFeatures) {
545 Log.v(
546 TAG,
547 "WindowInfoTracker Display Feature reported with bounds = "
548 + displayFeature.getBounds().toString()
549 + " and type = "
550 + displayFeature.getClass().getSimpleName());
551 if (displayFeature instanceof FoldingFeature) {
552 DisplayFeatureType type;
553 DisplayFeatureState state;
554 final FoldingFeature feature = (FoldingFeature) displayFeature;
555 if (feature.getOcclusionType() == OcclusionType.FULL) {
556 type = DisplayFeatureType.HINGE;
557 } else {
558 type = DisplayFeatureType.FOLD;
559 }
560 if (feature.getState() == State.FLAT) {
561 state = DisplayFeatureState.POSTURE_FLAT;
562 } else if (feature.getState() == State.HALF_OPENED) {
563 state = DisplayFeatureState.POSTURE_HALF_OPENED;
564 } else {
565 state = DisplayFeatureState.UNKNOWN;
566 }
567 result.add(new FlutterRenderer.DisplayFeature(displayFeature.getBounds(), type, state));
568 } else {
569 result.add(
570 new FlutterRenderer.DisplayFeature(
571 displayFeature.getBounds(),
572 DisplayFeatureType.UNKNOWN,
573 DisplayFeatureState.UNKNOWN));
574 }
575 }
576
577 // Data from the DisplayCutout bounds. Cutouts for cameras and other sensors are
578 // populated here. DisplayCutout was introduced in API 28.
579 if (Build.VERSION.SDK_INT >= API_LEVELS.API_28) {
580 WindowInsets insets = getRootWindowInsets();
581 if (insets != null) {
582 DisplayCutout cutout = insets.getDisplayCutout();
583 if (cutout != null) {
584 for (Rect bounds : cutout.getBoundingRects()) {
585 Log.v(TAG, "DisplayCutout area reported with bounds = " + bounds.toString());
586 result.add(new FlutterRenderer.DisplayFeature(bounds, DisplayFeatureType.CUTOUT));
587 }
588 }
589 }
590 }
591 viewportMetrics.displayFeatures = result;
592 sendViewportMetricsToFlutter();
593 }
AtkStateType state
GAsyncResult * result
Optional< SkRect > bounds
Definition SkRecords.h:189

Member Data Documentation

◆ renderSurface

RenderSurface io.flutter.embedding.android.FlutterView.renderSurface
package

Definition at line 115 of file FlutterView.java.


The documentation for this class was generated from the following file: