如何通过Flutter PlatformView创建原生TextView并实现文本更新?
使用Flutter PlatformView实现跨平台原生TextView并动态更新文本
一、Android端文本更新逻辑完善
你当前已完成初始文本传递,要实现动态更新,需通过MethodChannel在Flutter与原生Android间建立通信,步骤如下:
1. 补全Android原生PlatformView代码
在Android项目的PlatformView实现类(如NativeTextView)中集成MethodCallHandler,接收Flutter的更新指令:
class NativeTextView(context: Context, private val id: Int, params: Map<String?, Any?>) : PlatformView, MethodCallHandler { private val textView: TextView = TextView(context) private val channel: MethodChannel init { // 设置初始文本 val initialText = params["initialText"] as String? ?: "" textView.text = initialText textView.textSize = 20f textView.setTextColor(Color.BLACK) // 创建绑定当前View的MethodChannel channel = MethodChannel(context, "native_text_view_$id") channel.setMethodCallHandler(this) } override fun getView(): View = textView override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { when (call.method) { "setText" -> { val newText = call.argument<String>("text") ?: "" textView.text = newText result.success(null) } else -> result.notImplemented() } } override fun dispose() { channel.setMethodCallHandler(null) } }
同时确保PlatformViewFactory正确创建该View:
class NativeTextViewFactory(private val messenger: BinaryMessenger) : PlatformViewFactory(StandardMessageCodec.INSTANCE) { override fun create(context: Context, id: Int, params: Any?): PlatformView { val paramMap = params as Map<String?, Any?> return NativeTextView(context, id, paramMap) } }
在MainActivity中注册ViewType:
override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) flutterEngine.platformViewsController.registry.registerViewFactory( "INTEGRATION_ANDROID", NativeTextViewFactory(flutterEngine.dartExecutor.binaryMessenger) ) }
2. Flutter端改为StatefulWidget
原PlatformWidget为Stateless,无法保存controller引用,需改为Stateful以发送更新指令:
class PlatformWidget extends StatefulWidget { final String text; const PlatformWidget({super.key, required this.text}); @override State<PlatformWidget> createState() => _PlatformWidgetState(); } class _PlatformWidgetState extends State<PlatformWidget> { MethodChannel? _channel; @override Widget build(BuildContext context) { return PlatformViewLink( viewType: 'INTEGRATION_ANDROID', surfaceFactory: ( BuildContext context, PlatformViewController controller, ) { return AndroidViewSurface( controller: controller as AndroidViewController, gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{}, hitTestBehavior: PlatformViewHitTestBehavior.opaque, ); }, onCreatePlatformView: (PlatformViewCreationParams params) { final ExpensiveAndroidViewController controller = PlatformViewsService.initExpensiveAndroidView( id: params.id, viewType: params.viewType, layoutDirection: TextDirection.ltr, creationParams: {'initialText': widget.text}, creationParamsCodec: const StandardMessageCodec(), ); // 绑定MethodChannel _channel = MethodChannel('native_text_view_${params.id}'); controller ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated) ..create(); return controller; }, ); } // 对外暴露更新文本的方法 Future<void> updateText(String newText) async { await _channel?.invokeMethod('setText', {'text': newText}); } }
二、iOS端完整实现
1. iOS原生PlatformView代码
在iOS项目中创建NativeTextView.swift:
import Flutter import UIKit class NativeTextView: NSObject, FlutterPlatformView, FlutterMethodCallHandler { private let textView: UITextView private let channel: FlutterMethodChannel init(frame: CGRect, viewIdentifier: Int64, arguments: Any?, binaryMessenger: FlutterBinaryMessenger) { textView = UITextView(frame: frame) textView.font = UIFont.systemFont(ofSize: 20) textView.textColor = .black // 设置初始文本 if let params = arguments as? [String: Any], let initialText = params["initialText"] as? String { textView.text = initialText } // 创建MethodChannel channel = FlutterMethodChannel(name: "native_text_view_\(viewIdentifier)", binaryMessenger: binaryMessenger) super.init() channel.setMethodCallHandler(self) } func view() -> UIView { return textView } func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { switch call.method { case "setText": if let args = call.arguments as? [String: Any], let newText = args["text"] as? String { textView.text = newText result(nil) } else { result(FlutterError(code: "INVALID_ARGS", message: "参数错误", details: nil)) } default: result(FlutterMethodNotImplemented) } } } class NativeTextViewFactory: NSObject, FlutterPlatformViewFactory { private let messenger: FlutterBinaryMessenger init(messenger: FlutterBinaryMessenger) { self.messenger = messenger super.init() } func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView { return NativeTextView(frame: frame, viewIdentifier: viewId, arguments: args, binaryMessenger: messenger) } func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol { return FlutterStandardMessageCodec.sharedInstance() } }
在AppDelegate.swift中注册ViewType:
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController let factory = NativeTextViewFactory(messenger: controller.binaryMessenger) registrar(forPlugin: "INTEGRATION_IOS").register(factory, withId: "INTEGRATION_IOS") GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) }
2. Flutter端适配iOS
修改PlatformWidget,通过平台判断加载对应原生View:
import 'package:flutter/foundation.dart'; class PlatformWidget extends StatefulWidget { final String text; const PlatformWidget({super.key, required this.text}); @override State<PlatformWidget> createState() => _PlatformWidgetState(); } class _PlatformWidgetState extends State<PlatformWidget> { MethodChannel? _channel; @override Widget build(BuildContext context) { if (defaultTargetPlatform == TargetPlatform.android) { return PlatformViewLink( viewType: 'INTEGRATION_ANDROID', surfaceFactory: ( BuildContext context, PlatformViewController controller, ) { return AndroidViewSurface( controller: controller as AndroidViewController, gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{}, hitTestBehavior: PlatformViewHitTestBehavior.opaque, ); }, onCreatePlatformView: (PlatformViewCreationParams params) { final ExpensiveAndroidViewController controller = PlatformViewsService.initExpensiveAndroidView( id: params.id, viewType: params.viewType, layoutDirection: TextDirection.ltr, creationParams: {'initialText': widget.text}, creationParamsCodec: const StandardMessageCodec(), ); _channel = MethodChannel('native_text_view_${params.id}'); controller ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated) ..create(); return controller; }, ); } else if (defaultTargetPlatform == TargetPlatform.iOS) { return UiKitView( viewType: 'INTEGRATION_IOS', creationParams: {'initialText': widget.text}, creationParamsCodec: const StandardMessageCodec(), onPlatformViewCreated: (int id) { _channel = MethodChannel('native_text_view_$id'); }, ); } else { return const Text('不支持的平台'); } } Future<void> updateText(String newText) async { await _channel?.invokeMethod('setText', {'text': newText}); } }
三、点击按钮更新文本的使用示例
通过GlobalKey调用PlatformWidget的更新方法:
class HomePage extends StatefulWidget { const HomePage({super.key}); @override State<HomePage> createState() => _HomePageState(); } class _HomePageState extends State<HomePage> { final _platformWidgetKey = GlobalKey<_PlatformWidgetState>(); int _count = 0; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text('原生TextView更新示例')), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ PlatformWidget( key: _platformWidgetKey, text: '初始文本', ), const SizedBox(height: 30), ElevatedButton( onPressed: () { _count++; _platformWidgetKey.currentState?.updateText('更新后的文本:$_count'); }, child: const Text('点击更新文本'), ), ], ), ), ); } }
内容的提问来源于stack exchange,提问作者rradjabs
相关产品推荐
相关产品推荐

