Flutter中嵌入Android 原生TextView實例教程
前言
本篇文章 中寫到的是 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) {//創建 TextViewTextView 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);}}@Overridepublic View getView() {return mTestTextView;}@Overridepublic 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')@Overridepublic PlatformView create(Context context, int id, Object args) {//flutter 傳遞過來的參數Map<String, Object> params = (Map<String, Object>) args;//創建 TestTextViewreturn 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;//初始化 PluginRegistryPluginRegistry.Registrar registrar = registry.registrarFor(key);//設置標識registrar.platformViewRegistry().registerViewFactory('com.flutter_to_native_test_textview', new TestViewFactory(registrar.messenger()));}}
MainActivity 中注冊
import android.os.Bundleimport io.flutter.app.FlutterActivityimport io.flutter.plugins.FlutterToAndroidPluginsimport io.flutter.plugins.GeneratedPluginRegistrantclass 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);}... ...@Overridepublic 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
總結
到此這篇關于Flutter中嵌入Android 原生TextView實例教程的文章就介紹到這了,更多相關Flutter嵌入Android 原生TextView內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!
相關文章:
