内容简介:最近想要实现一个flutter地图插件,但是flutter只提供了基于google map的官方插件,所以想要使用高德地图和百度地图自己做一个,就看到了这篇文章,顺便翻译一下分享给大家。这里先贴出google map插件文章以便有梯子的同学可以直接使用Flutter最近刚刚有了一个新的组件叫做
最近想要实现一个flutter地图插件,但是flutter只提供了基于google map的官方插件,所以想要使用高德地图和百度地图自己做一个,就看到了这篇文章,顺便翻译一下分享给大家。
这里先贴出google map插件文章以便有梯子的同学可以直接使用 Exploring Google Maps in Flutter
译文
Flutter最近刚刚有了一个新的组件叫做 PlatformView
,它允许开发者在flutter里面嵌入Android原生的view。这一开放举措为实现注入地图和webview提供了许多新的可能。( github.com/flutter/flu… ).
在这篇教程里,我们将探索如何创建一个 TextViewPlugin
,在plugin里我们会暴露一个android原生TextView作为flutter组件。
在进入代码实现之前需要注意以下几点:
- 目前只支持Android(作者文章发布于2018.9.7, 目前已经支持ios )。
- 需要android api版本在20及以上。
- 嵌入Android views是一个昂贵的操作,所以应当避免在flutter能够实现的情况下去使用它。
- 嵌入Android view的绘制和其他任何flutter widget一样,view的转换也同样使用。
- 组件会撑满所有可获得控件,因此它的父组件需要提供一个布局边界。
- 需要切换到flutter的master分支上使用(目前已经不需要)
下面开始实现部分
第一步就是创建一个flutter plugin项目。
在flutter plugin项目创建完成之后在 ./lib/text_view.dart
创建TextView类。
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(new TextViewController._(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); } } 复制代码
一个需要重点注意的是当我们在上面代码第24行创建了 AndroidView
,我们需要提供一个 viewType
,会在稍后介绍。
我们还提供了一个 onPlatformCompleted
实现,以便我们可以为 TextView
小部件提供一个 TextViewController
,然后可以使用它来使用 setText
方法更新它的文本。
完整的 AndroidView
文档请见 docs.flutter.io/flutter/wid…
接下来我们需要实现Android部分的 TextViewPlugin
。
我们打开另一个生成文件 ./android/src/main/java/{organization_name}/TextViewPlugin.java
,用一下内容替换文件内的内容。
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", new TextViewFactory(registrar.messenger())); } } 复制代码
我们需要做的就是实现 registerWith
方法,传入 text_view.dart
中定义的 viewType
,同时提供一个 TextViewFactory
,它将会创建原生 TextView
作为 PlatformView
。
接着我们需要创建 ./android/src/main/java/{organization_name}/TextViewFactory.java
,并继承 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 new FlutterTextView(context, messenger, id); } } 复制代码
TextViewFactory
实现了create方法,它会返回 PlatformView
,在我们的例子里叫做 FlutterTextView
。
然后,创建 ./android/src/main/java/{organization_name}/FlutterTextView.java
并且实现 PlatformView
和 MethodCallHandler
以至于我们可以将原生view绘制到flutter组件并且通过 MethodChannel
从dart接收数据。
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() { 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() {} } 复制代码
FlutterTextView
创建了一个新的 TextView
并且设置了一个 MethodChannel
,因此TextView可以从dart代码接收数据进行视图更新。
为了实现 PlatformView
,我们需要重写 getView
方法返回textview对象,同时重写 dispose
方法。
为了实现 MethodCallHandler
,需要重写 onMethodCall
,在接收到 setText 调用指令时候更新TextView,或者在不支持的其他指令情况下返回 result.notImplemented
。
现在可以测试我们的新 TextView
组件。
打开 ./example/lib/main.dart
用下面的代码替换。
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!'); } } 复制代码
代码看着很熟悉,我们运行一个 MaterialApp
,最外层用 Scaffold
。有一个 TextView
用 Container
包裹,这个container组件作为一个垂直排列组件的第一个子组件,第二个子组件是一个flutter Text
。
我们同样实现了方法 onTextViewCreated
,在这个方法里面去调用 setText
。
这个例子证明了可以对任何原生Android view转换成flutterwidget,并且像其他flutter组件一样绘制和转换。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 动手创建一个自己的「React native」原生模块
- NativeScript 3.4.0 发布,创建跨平台原生应用的框架
- NativeScript 4.0.0 发布,创建跨平台原生应用的框架
- NativeScript 4.0.1 发布,创建跨平台原生应用的框架
- 使用HTML5原生对话框元素,轻松创建模态框组件
- 零信任原生安全:超越云原生安全
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
The Haskell School of Music
Paul Hudak、Donya Quick / Cambridge University Press / 2018-10-4 / GBP 42.99
This book teaches functional programming through creative applications in music and sound synthesis. Readers will learn the Haskell programming language and explore numerous ways to create music and d......一起来看看 《The Haskell School of Music》 这本书的介绍吧!