内容简介:最近想要实现一个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原生对话框元素,轻松创建模态框组件
- 零信任原生安全:超越云原生安全
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Python高效开发实战——Django、Tornado、Flask、Twisted(第2版)
刘长龙 / 电子工业出版社 / 2019-1 / 99
也许你听说过全栈工程师,他们善于设计系统架构,精通数据库建模、通用网络协议、后端并发处理、前端界面设计,在学术研究或工程项目上能独当一面。通过对Python 3及相关Web框架的学习和实践,你就可以成为这样的全能型人才。 《Python高效开发实战——Django、Tornado、Flask、Twisted(第2版)》分为3篇:上篇是Python基础,带领初学者实践Python开发环境,掌握......一起来看看 《Python高效开发实战——Django、Tornado、Flask、Twisted(第2版)》 这本书的介绍吧!