Flutter中嵌入Android 原生TextView实例教程
作者:早起的年轻人 发布时间:2023-07-05 02:02:00
前言
本篇文章 中写到的是 flutter 调用了Android 原生的 TextView 案例
添加原生组件的流程基本上可以描述为:
1 android 端实现原生组件PlatformView提供原生view
2 android 端创建PlatformViewFactory用于生成PlatformView
3 android 端创建FlutterPlugin用于注册原生组件
4 flutter 平台嵌入 原生view
1 创建原生组件
创建在fLutter工程时会生成几个文件夹,lib是放flutter工程代码,android和ios文件夹分别是对应的双平台的原生工程。
在这里直接打开Android工程目录,项目默认生成了GeneratedPluginRegistrant和MainActivity两个文件,GeneratedPluginRegistrant不要动,GeneratedPluginRegistrant是flutter中配制使用其他插件时,程序在编译时自动进行插件注册使用的类。
在MainActivity的包下新建自定义View,Flutter的原生View不能直接继承自View,需要实现提供的PlatformView接口:
public class TestTextView implements PlatformView r{
private final TextView mTestTextView;
/**
*
* @param context
* @param messenger
* @param id
* @param params 初始化时 flutter 传递过来的参数
*/
TestTextView(Context context, BinaryMessenger messenger, int id, Map<String, Object> params) {
//创建 TextView
TextView lTextView = new TextView(context);
lTextView.setText("Android的原生TextView");
this.mTestTextView = lTextView;
//flutter 传递过来的参数
if (params!=null&¶ms.containsKey("content")) {
String myContent = (String) params.get("content");
lTextView.setText(myContent);
}
}
@Override
public View getView() {
return mTestTextView;
}
@Override
public void dispose() {
}
}
2 创建PlatformViewFactory
import android.content.Context;
import java.util.Map;
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 TestViewFactory extends PlatformViewFactory {
private final BinaryMessenger messenger;
public TestViewFactory(BinaryMessenger messenger) {
super(StandardMessageCodec.INSTANCE);
this.messenger = messenger;
}
/**
*
* @param context
* @param id
* @param args args是由Flutter传过来的自定义参数
* @return
*/
@SuppressWarnings("unchecked")
@Override
public PlatformView create(Context context, int id, Object args) {
//flutter 传递过来的参数
Map<String, Object> params = (Map<String, Object>) args;
//创建 TestTextView
return new TestTextView(context, messenger, id, params);
}
3 创建Plugin并在ManActivity中注册插件
/**
* flutter 调用 android 原生view
*
*/
public class TestFluttertoAndroidTextViewPlugin {
public static void registerWith(PluginRegistry registry) {
//防止多次注册
final String key = TestFluttertoAndroidTextViewPlugin.class.getCanonicalName();
if (registry.hasPlugin(key)) return;
//初始化 PluginRegistry
PluginRegistry.Registrar registrar = registry.registrarFor(key);
//设置标识
registrar.platformViewRegistry().registerViewFactory("com.flutter_to_native_test_textview", new TestViewFactory(registrar.messenger()));
}
}
MainActivity 中注册
import android.os.Bundle
import io.flutter.app.FlutterActivity
import io.flutter.plugins.FlutterToAndroidPlugins
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
//flutter 项目工程中默认生成的
GeneratedPluginRegistrant.registerWith(this)
//这是我们新创建的插件
TestFluttertoAndroidTextViewPlugin.registerWith(this)
}
override fun onDestroy() {
super.onDestroy()
}
}
4 flutter页面中嵌入android 原生Textview
4.1 最简单的调用
//这里设置的 viewType值与 android 中插件注册的标识 一至
//registrar.platformViewRegistry().registerViewFactory("com.flutter_to_native_test_textview", new TestViewFactory(registrar.messenger()));
mTextWidget = Container(
height: 200,
child: AndroidView(
//设置标识
viewType: "com.flutter_to_native_test_textview",
),
);
@override
Widget build(BuildContext context) {
// TODO: implement build
return Scaffold(
appBar: appBar,
//显示的页面
body: mTextWidget,
);
}
4.2 flutter 调用 原生view并传参数
mTextWidget = Container(
height: 200,
child: AndroidView(
//标识
viewType: "com.flutter_to_native_test_textview",
creationParams: {
"content": "flutter 传入的文本内容",
},
//参数的编码方式
creationParamsCodec: const StandardMessageCodec(),
),
);
android 原生中的接收(只会接收一次)
... ...
TestTextView(Context context, BinaryMessenger messenger, int id, Map<String, Object> params) {
... ..
//flutter 传递过来的参数
if (params!=null&&!params.isEmpty()&¶ms.containsKey("content")) {
String myContent = (String) params.get("content");
lTextView.setText(myContent);
}
... ...
}
4.3 flutter 更新 原生view 中的数据
原生组件初始化的参数并不会随着setState重复赋值,可以通过MethodCall来实现更新数据。
首先让原生view组件实现MethodCallHandler接口:
public class TestTextView implements PlatformView , MethodChannel.MethodCallHandler{
private final TextView mTestTextView;
TestTextView(Context context, BinaryMessenger messenger, int id, Map<String, Object> params) {
... ...
//com.flutter_to_native_test_view_ 是更新数据的通信标识
MethodChannel methodChannel = new MethodChannel(messenger, "com.flutter_to_native_test_textview_" + id);
methodChannel.setMethodCallHandler(this);
}
... ...
@Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
//updateText 是flutter 中调用的方法名称,可以随意定义
if ("updateText".equals(methodCall.method)) {
String text = (String) methodCall.arguments;
this.mTestTextView .setText(text);
//对flutter 的回调
result.success(null);
}
}
}
flutter 中调用 android 原生view
MethodChannel _channel;
int viewId=0;
mTextWidget = Container(
height: 200,
child: AndroidView(
//标识
viewType: "com.flutter_to_native_test_textview",
creationParams: {
"content": "flutter 传入的文本内容",
},
//参数的编码方式
creationParamsCodec: const StandardMessageCodec(),
//view创建完成时的回调
onPlatformViewCreated: (id) {
viewId = id;
},
),
);
更新数据
//这里设置的标识 MethodChannel('com.flutter_to_native_test_textview_$viewId');
// 与android MethodChannel methodChannel = new MethodChannel(messenger, "com.flutter_to_native_test_textview_" + id); 中注册的一至
void clickUpdtae(){
_channel = new MethodChannel('com.flutter_to_native_test_textview_$viewId');
updateTextView();
}
//这里的标识 updateText
//与android 中接收消息的方法中
//if ("updateText".equals(methodCall.method)) {...} 一至
void updateTextView() async {
return _channel.invokeMethod('updateText', "更新内容");
}
通过onPlatformViewCreated回调,监听原始组件成功创建,并能够在回调方法的参数中拿到当前组件的id,这个id是系统随机分配的,然后通过这个分配的id加上我们的组件名称最为前缀创建一个和组件通讯的MethodChannel,拿到channel对象之后就可以通过invokeMethod方法向原生组件发送消息了,这里这里调用的是‘updateText'这个方法,参数是一个String
来源:https://blog.csdn.net/zl18603543572/article/details/95983215


猜你喜欢
- 记得老师讲课的时候,经常会用PPT遥控翻页笔来遥控幻灯片来给我们讲课,当时觉得非常有趣,由于这段时间接触了VSTO相关的开发,了解到了Off
- 最近项目中需要用到IO流来读取图片以提供前台页面展示,由于以前一直是用url路径的方式进行图片展示,一听说要项目要用IO流读取图片感觉好复杂
- 消费逻辑上文 流式图表框架搭建框架搭建好之后着手开发下kafka的核心消费逻辑,流式图表的核心消费逻辑就是实现一个消费链接池维护消
- /* String name = "adsbsadgsadgtewterfsdf"
- 本文实例讲述了Java二叉搜索树基础原理与实现方法。分享给大家供大家参考,具体如下:前言:本文通过先通过了解一些二叉树基础知识,然后在转向学
- 一、滑动验证码生成思路1、随机选择一张图片2、生成滑块起点位置(x, y)3、生成滑块轮廓4、抠出滑块5、将滑块部位去除颜色二、主要方法这里
- 前言现在不少应用都是采用了混合开发模式,不论是原生加RN,或是原生加Flutter,或是原生加H5。原生实现主业务线,其他部分可以借助跨平台
- 一、前言最近自己在学习Spring boot的过程中开发了一个组件 multithreadpool-spring-boot-starter,
- 在Android开发中我们经常有这样的需求,从服务器上下载xml或者JSON类型的数据,其中包括一些图片资源,本demo模拟了这个需求,从网
- 需求:如上图,需要隐藏右上角的多用户蓝色图标.修改后结果如下:锁屏相关的布局在SystemUIframeworks/base/package
- 通过Class对象获取对象的方式是通过class.newInstance()方式获取,通过调用默认构造参数实例化一个对象。/** * Cre
- 最近在学ssh,一直搞不懂$,%,#的区别,做了点小练习,慢慢也懂了一点,将自己所学的也记录下来吧。 存在一下一个实
- 类的定义面向对象的程序设计中,类可以看作是我们自定义的数据类型,那么,如何能更加优美,更加高效地定义它就显得尤为重要。类中的成员有很多,每一
- 一、String类String类在java.lang包中,java使用String类创建一个字符串变量,字符串变量属于对象。java把Str
- 定义:使多个对象都有机会处理请求,从而避免了请求的发送者和接收者之间的耦合关系。将这些对象连成一条链,并沿着这条链传递该请求,直到有对象处理
- jasperreport导出的pdf每页显示的记录太少主要是确保Details的高度与Details中Field Text的高度一致。jas
- 购物车项目,业务需要实现了一个购物车的项目,简单的了解下实现逻辑:数据计算等是在Adapter中计算出来的,通过在Adapter中计算出来的
- 本文以实例形式展示了Android实现Activity界面切换添加动画特效的方法,对于Android程序设计人员来说有很好的参考借鉴价值。具
- 前言我们利用printf 函数实现一个在屏幕上弹跳的小球,如图所示。弹跳的小球游戏比较简单、容易入门,也是反弹球消砖块、接金币、台球等很多游
- 1、为什么需要自定义ViewAndroid系统内置的View不满足我们的业务需求2、自定义View的基本方法onMeasure:决定着Vie