Class FlutterView

All Implemented Interfaces:
Drawable.Callback, AccessibilityEventSource, KeyEvent.Callback, ViewManager, ViewParent, KeyboardManager.ViewDelegate, io.flutter.plugin.mouse.MouseCursorPlugin.MouseCursorViewDelegate

public class FlutterView extends FrameLayout implements io.flutter.plugin.mouse.MouseCursorPlugin.MouseCursorViewDelegate, KeyboardManager.ViewDelegate
Displays a Flutter UI on an Android device.

A FlutterView's UI is painted by a corresponding FlutterEngine.

A FlutterView can operate in 2 different RenderModes:

  1. RenderMode.surface, which paints a Flutter UI to a 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 SurfaceTexture are required, developers should strongly prefer this render mode.
  2. RenderMode.texture, which paints a Flutter UI to a SurfaceTexture. This mode is not as performant as 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 SurfaceTexture are required, developers should strongly prefer the RenderMode.surface render mode.
See https://source.android.com/devices/graphics/arch-tv#surface_or_texture for more information comparing SurfaceView and TextureView.
  • Constructor Details

  • Method Details

    • hasRenderedFirstFrame

      public boolean hasRenderedFirstFrame()
      Returns true if an attached FlutterEngine has rendered at least 1 frame to this FlutterView.

      Returns false if no FlutterEngine is attached.

      This flag is specific to a given 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
    • addOnFirstFrameRenderedListener

      public void addOnFirstFrameRenderedListener(@NonNull FlutterUiDisplayListener listener)
      Adds the given listener to this FlutterView, to be notified upon Flutter's first rendered frame.
    • removeOnFirstFrameRenderedListener

      public void removeOnFirstFrameRenderedListener(@NonNull FlutterUiDisplayListener listener)
      Removes the given listener, which was previously added with addOnFirstFrameRenderedListener(FlutterUiDisplayListener).
    • onConfigurationChanged

      protected void onConfigurationChanged(@NonNull Configuration newConfig)
      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.

      Overrides:
      onConfigurationChanged in class View
    • onSizeChanged

      protected void onSizeChanged(int width, int height, int oldWidth, int oldHeight)
      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.

      Overrides:
      onSizeChanged in class View
    • createWindowInfoRepo

      @VisibleForTesting protected WindowInfoRepositoryCallbackAdapterWrapper createWindowInfoRepo()
    • onAttachedToWindow

      protected void onAttachedToWindow()
      Invoked when this is attached to the window.

      We register for WindowInfoTracker updates.

      Overrides:
      onAttachedToWindow in class ViewGroup
    • onDetachedFromWindow

      protected void onDetachedFromWindow()
      Invoked when this is detached from the window.

      We unregister from WindowInfoTracker updates.

      Overrides:
      onDetachedFromWindow in class ViewGroup
    • setWindowInfoListenerDisplayFeatures

      protected void setWindowInfoListenerDisplayFeatures(androidx.window.layout.WindowLayoutInfo layoutInfo)
      Refresh WindowInfoTracker and DisplayCutout display features. Fold, hinge and cutout areas are populated here.
    • onApplyWindowInsets

      @NonNull public final WindowInsets onApplyWindowInsets(@NonNull WindowInsets insets)
      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.

      Overrides:
      onApplyWindowInsets in class View
    • onCreateInputConnection

      @Nullable public InputConnection onCreateInputConnection(@NonNull EditorInfo outAttrs)
      Creates an InputConnection to work with a 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.

      Overrides:
      onCreateInputConnection in class View
    • checkInputConnectionProxy

      public boolean checkInputConnectionProxy(View view)
      Allows a View that is not currently the input connection target to invoke commands on the 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.

      Overrides:
      checkInputConnectionProxy in class View
    • dispatchKeyEvent

      public boolean dispatchKeyEvent(@NonNull KeyEvent event)
      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.

      Overrides:
      dispatchKeyEvent in class ViewGroup
    • onTouchEvent

      public boolean onTouchEvent(@NonNull MotionEvent event)
      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.

      Overrides:
      onTouchEvent in class View
    • onGenericMotionEvent

      public boolean onGenericMotionEvent(@NonNull MotionEvent event)
      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.

      Overrides:
      onGenericMotionEvent in class View
    • onHoverEvent

      public boolean onHoverEvent(@NonNull MotionEvent event)
      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.

      Overrides:
      onHoverEvent in class View
    • getAccessibilityNodeProvider

      @Nullable public AccessibilityNodeProvider getAccessibilityNodeProvider()
      Overrides:
      getAccessibilityNodeProvider in class View
    • findViewByAccessibilityIdTraversal

      @Nullable public View findViewByAccessibilityIdTraversal(int accessibilityId)
      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:
      accessibilityId - The view accessibility id.
      Returns:
      The view matching the accessibility id if any.
    • getSystemPointerIcon

      @RequiresApi(24) @NonNull public PointerIcon getSystemPointerIcon(int type)
      Description copied from interface: io.flutter.plugin.mouse.MouseCursorPlugin.MouseCursorViewDelegate
      Gets a system pointer icon object for the given type.

      If typeis not recognized, returns the default pointer icon.

      This is typically implemented by calling PointerIcon.getSystemIcon(android.content.Context, int) with the context associated with this view.

      Specified by:
      getSystemPointerIcon in interface io.flutter.plugin.mouse.MouseCursorPlugin.MouseCursorViewDelegate
    • getBinaryMessenger

      public BinaryMessenger getBinaryMessenger()
      Description copied from interface: KeyboardManager.ViewDelegate
      Returns a BinaryMessenger to send platform messages with.
      Specified by:
      getBinaryMessenger in interface KeyboardManager.ViewDelegate
    • onTextInputKeyEvent

      public boolean onTextInputKeyEvent(@NonNull KeyEvent keyEvent)
      Description copied from interface: KeyboardManager.ViewDelegate
      Send a KeyEvent that is not handled by the keyboard responders to the text input system.
      Specified by:
      onTextInputKeyEvent in interface KeyboardManager.ViewDelegate
      Parameters:
      keyEvent - the KeyEvent that should be processed by the text input system. It must not be null.
      Returns:
      Whether the text input handles the key event.
    • redispatch

      public void redispatch(@NonNull KeyEvent keyEvent)
      Description copied from interface: KeyboardManager.ViewDelegate
      Send a KeyEvent that is not handled by Flutter back to the platform.
      Specified by:
      redispatch in interface KeyboardManager.ViewDelegate
    • attachToFlutterEngine

      public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine)
      Connects this FlutterView to the given 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 FlutterEngine, e.g., user touch events, accessibility events, keyboard events, and others.

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

    • detachFromFlutterEngine

      public void detachFromFlutterEngine()
      Disconnects this FlutterView from a previously attached FlutterEngine.

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

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

    • createImageView

      @VisibleForTesting @NonNull public FlutterImageView createImageView()
    • getCurrentImageSurface

      @VisibleForTesting public FlutterImageView getCurrentImageSurface()
    • convertToImageView

      public void convertToImageView()
      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.
    • revertImageView

      public void revertImageView(@NonNull Runnable onDone)
      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:
      onDone - a callback called when Flutter UI is rendered on the previous surface. Use this callback to perform cleanups. For example, destroy overlay surfaces.
    • attachOverlaySurfaceToRender

      public void attachOverlaySurfaceToRender(@NonNull FlutterImageView view)
    • acquireLatestImageViewFrame

      public boolean acquireLatestImageViewFrame()
    • isAttachedToFlutterEngine

      @VisibleForTesting public boolean isAttachedToFlutterEngine()
      Returns true if this FlutterView is currently attached to a FlutterEngine.
    • getAttachedFlutterEngine

      @VisibleForTesting @Nullable public FlutterEngine getAttachedFlutterEngine()
      Returns the FlutterEngine to which this FlutterView is currently attached, or null if this FlutterView is not currently attached to a FlutterEngine.
    • addFlutterEngineAttachmentListener

      @VisibleForTesting public void addFlutterEngineAttachmentListener(@NonNull FlutterView.FlutterEngineAttachmentListener listener)
      Adds a FlutterView.FlutterEngineAttachmentListener, which is notified whenever this FlutterView attached to/detaches from a FlutterEngine.
    • removeFlutterEngineAttachmentListener

      @VisibleForTesting public void removeFlutterEngineAttachmentListener(@NonNull FlutterView.FlutterEngineAttachmentListener listener)
    • onProvideAutofillVirtualStructure

      public void onProvideAutofillVirtualStructure(@NonNull ViewStructure structure, int flags)
      Overrides:
      onProvideAutofillVirtualStructure in class View
    • autofill

      public void autofill(@NonNull SparseArray<AutofillValue> values)
      Overrides:
      autofill in class View
    • setVisibility

      public void setVisibility(int visibility)
      Overrides:
      setVisibility in class View