Flutter PlatformView: How to create Widgets from Native Views
Flutter just recently got a new widget called PlatformView
which allows developers to embed Android Views in the flutter widget hierarchy. This opens the door to many new possibilities like fully integrated maps and webviews (https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/widgets/platform_view.dart).
In this tutorial, we’re going to go through how to create a TextViewPlugin
where we expose a native android TextView
as a Flutter Widget.
Before we jump into the code some quick things to note are:
- Currently only supported for Android (should be coming in the next few weeks for iOS)
- Requires Android API level 20 or greater.
- Embedding Android views is an expensive operation and should be avoided when a Flutter equivalent is possible.
- The embedded Android view is painted just like any other Flutter widget and transformations apply to it as well.
- The widget will fill all available space therefore the parent of this object must provide bounded layout constraints.
- As of now, you need to switch to the flutter master channel in order to follow along. You can do that by running
flutter channel master
and making sure your new Flutter Project is pointing to the master branch of the flutter sdk.
Time to start coding :)
The first thing we’re going to need to do is create a new flutter plugin:
After the Flutter Plugin has been created we can start by creating our TextView
class in ./lib/text_view.dart
An important thing to note is when we create the AndroidView
on line 24 we need to provide a viewType
which we will get to in a bit.
We additionally provide an onPlatformCompleted
implementation so that we can provide our TextView
widget with a TextViewController
which it can then use to update it’s text using the setText
method.
For the full AndroidView
documentation check out https://docs.flutter.io/flutter/widgets/AndroidView-class.html.
Next we need to work on the Android implementation of our TextViewPlugin
.
We will start by opening another generated file called ./android/src/main/java/{organization_name}/TextViewPlugin.java
. We can replace the contents of that file with the following:
All we are doing is implementing the registerWith
method where we provide the viewType
we defined earlier in text_view.dart
as well as providing a TextViewFactory
which will be creating our native TextView
as a PlatformView
.
Next, we need to create ./android/src/main/java/{organization_name}/TextViewFactory.java
and extend PlatformViewFactory
.
Our TextViewFactory
implements the create
method which returns a PlatformView
(in our case it will return a FlutterTextView
).
Next up, we need to create ./android/src/main/java/{organization_name}/FlutterTextView.java
and implement PlatformView
as well as MethodCallHandler
so that we can have our native view painted as a flutter widget and be able to receive data from dart via a MethodChannel
.
Our FlutterTextView
creates a new TextView
and sets up a MethodChannel
so that the TextView
can receive data from dart code and make updates (in this case update the text).
In order to implement PlatformView
, we need to override getView
and return our textView
as well as override dispose
(which in this case does nothing).
In order to implement MethodCallHandler
, we need to override onMethodCall
and, depending on the method, either call our internal setText
method (to update the textView
's text) or return result.notImplemented
since we currently don’t support any other methods.
Now it’s time to test our new TextView
widget!
Open ./example/lib/main.dart
and replace it with the following code:
This should look familiar. We are running a MaterialApp
that renders a Scaffold
. We have our TextView
widget nested within a Container
widget (with some padding) which is embedded within a Center
widget. The Center
widget is the first child of a Column
widget. Our Column
’s second child is an Expanded
widget and it contains a Container
widget with the built in flutter Text
widget.
We also have our implementation for onTextViewCreated
where we call the setText
method.
It’s time to run our example flutter app and take a look at what we’ve built.
Awesome! Even though you’d normally just use the built in flutter Text
widget to accomplish this, we’ve proven that you can now “widgetize” any native Android view which is pretty powerful.
This example flutter app demonstrates that our TextView
is painted just like any other Flutter widget and transformations apply to it as well.
We still need to write tests for our plugin in order for it to be production ready so we’ll do that in a follow up article. You can check out the complete source code at https://github.com/felangel/flutter_text_view_plugin.