Originally from flutter Community

Medium.com/flutter-com…).

originally

Recently, I wanted to implement a Plugin for Flutter map, but flutter only provides the official plugin based on Google Map, so I want to use Autoramap and Baidu Map to make my own plugin. I saw this article, by the way, TRANSLATE and share it with you.

Google Maps in Flutter can be used by students with ladders

The translation

Flutter has just had a new component called PlatformView that allows developers to embed Android native Views into Flutter. This openness opens up many new possibilities for injecting maps and WebViews. (github.com/flutter/flu…). .

In this tutorial we will explore how to create a TextViewPlugin in which we expose an Android native TextView as a Flutter component.

Before entering the code implementation, note the following:

  • It is currently only available on Android (published on July 7, 2018, ios already available).
  • Android API version 20 or later is required.
  • Embedding Android Views is an expensive operation, so avoid using it if Flutter can be implemented.
  • The rendering of the embedded Android View is the same as any other Flutter widget. The view conversion is also used.
  • The component fills all available controls, so its parent component needs to provide a layout boundary.
  • Switch to the Master branch of the Flutter (no longer needed)

Let’s start the implementation part

The first step is to create a Flutter Plugin project.

Dart create TextView classes in./lib/text_view.dart after the flutter plugin project is created.

import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

typedef void TextViewCreatedCallback(TextViewController controller);

class TextView extends StatefulWidget {
  const TextView({
    Key key,
    this.onTextViewCreated,
  }) : super(key: key);

  final TextViewCreatedCallback onTextViewCreated;

  @override
  State<StatefulWidget> createState() => _TextViewState();
}

class _TextViewState extends State<TextView> {
  @override
  Widget build(BuildContext context) {
    if (defaultTargetPlatform == TargetPlatform.android) {
      return AndroidView(
        viewType: 'plugins.felix.angelov/textview',
        onPlatformViewCreated: _onPlatformViewCreated,
      );
    }
    return Text(
        '$defaultTargetPlatform is not yet supported by the text_view plugin');
  }

  void _onPlatformViewCreated(int id) {
    if (widget.onTextViewCreated == null) {
      return;
    }
    widget.onTextViewCreated(newTextViewController._(id)); }}class TextViewController {
  TextViewController._(int id)
      : _channel = new MethodChannel('plugins.felix.angelov/textview_$id');

  final MethodChannel _channel;

  Future<void> setText(String text) async {
    assert(text ! =null);
    return _channel.invokeMethod('setText', text); }}Copy the code

One important thing to note is that when we create AndroidView at line 24 above, we need to provide a viewType, which we’ll cover later.

We also provide an onPlatformCompleted implementation so that we can provide a TextViewController for the TextView widget, which we can then use to update its text using the setText method.

Complete AndroidView document please see docs. Flutter. IO/flutter/wid…

Next we need to implement the TextViewPlugin for the Android part.

Open another generate file./android/ SRC /main/ Java /{organization_name}/ textViewplugin.java and replace the contents with the following.

package angelov.felix.textview;

import io.flutter.plugin.common.PluginRegistry.Registrar;

public class TextViewPlugin {
  public static void registerWith(Registrar registrar) {
    registrar
            .platformViewRegistry()
            .registerViewFactory(
                    "plugins.felix.angelov/textview".newTextViewFactory(registrar.messenger())); }}Copy the code

All we need to do is implement the registerWith method, pass in the viewType defined in text_view.dart, and provide a TextViewFactory that will create the native TextView as a PlatformView.

Next we need to create./android/ SRC /main/ Java /{organization_name}/ textViewFactory.java and inherit PlatformViewFactory

package angelov.felix.textview;

import android.content.Context;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugin.platform.PlatformViewFactory;

public class TextViewFactory extends PlatformViewFactory {
    private final BinaryMessenger messenger;

    public TextViewFactory(BinaryMessenger messenger) {
        super(StandardMessageCodec.INSTANCE);
        this.messenger = messenger;
    }

    @Override
    public PlatformView create(Context context, int id, Object o) {
        return newFlutterTextView(context, messenger, id); }}Copy the code

TextViewFactory implements the create method, which returns a PlatformView, called FlutterTextView in our case.

And then, Create./android/ SRC /main/ Java /{organization_name}/FlutterTextView.java and implement PlatformView and MethodCallHandler so that we can draw the native View to Flu The tter component also receives data from dart through the MethodChannel.

package angelov.felix.textview;

import android.content.Context;
import android.view.View;
import android.widget.TextView;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import static io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import static io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.platform.PlatformView;

public class FlutterTextView implements PlatformView.MethodCallHandler  {
    private final TextView textView;
    private final MethodChannel methodChannel;

    FlutterTextView(Context context, BinaryMessenger messenger, int id) {
        textView = new TextView(context);
        methodChannel = new MethodChannel(messenger, "plugins.felix.angelov/textview_" + id);
        methodChannel.setMethodCallHandler(this);
    }

    @Override
    public View getView(a) {
        return textView;
    }

    @Override
    public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
        switch (methodCall.method) {
            case "setText":
                setText(methodCall, result);
                break;
            default: result.notImplemented(); }}private void setText(MethodCall methodCall, Result result) {
        String text = (String) methodCall.arguments;
        textView.setText(text);
        result.success(null);
    }

    @Override
    public void dispose(a) {}}Copy the code

FlutterTextView creates a new TextView and sets a MethodChannel, so the TextView can receive data from the DART code for view updates.

To implement PlatformView, we need to override the getView method to return the TextView object as well as the Dispose method.

To implement MethodCallHandler, you need to override the onMethodCall, update the TextView when a setText call is received, or return result.notimplemented if other instructions are not supported.

Now you can test our new TextView component.

Open./example/lib/main.dart and replace it with the following code.

import 'package:flutter/material.dart';
import 'package:text_view/text_view.dart';

void main() => runApp(MaterialApp(home: TextViewExample()));

class TextViewExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(title: const Text('Flutter TextView example')),
        body: Column(children: [
          Center(
              child: Container(
                  padding: EdgeInsets.symmetric(vertical: 30.0),
                  width: 130.0,
                  height: 100.0,
                  child: TextView(
                    onTextViewCreated: _onTextViewCreated,
                  ))),
          Expanded(
              flex: 3,
              child: Container(
                  color: Colors.blue[100],
                  child: Center(child: Text("Hello from Flutter!")))))); }void _onTextViewCreated(TextViewController controller) {
    controller.setText('Hello from Android! '); }}Copy the code

The code looks familiar. We run a MaterialApp using the Scaffold for the outermost layer. There is a TextView wrapped in a Container. The Container component acts as the first child of a vertically aligned component. The second child is a Flutter Text.

We also implement the onTextViewCreated method, which calls setText in this method.

This example demonstrates that any native Android View can be converted into a Flutter Widget and drawn and converted just like any other Flutter component.