You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 17:53:16