flutter中嵌入原生Android View

一、创建Android原生View

1、选中android目录下任意文件,点击右上角出现的“Open for Editing in Android Studio”

2、在新打开的窗口里,app项目下创建继承PlatformView 的AndroidView

/**
 * messenger   flutter与原生通讯需要该参数
 * viewId      控件唯一标识
 * args        初始化参数
 */
class AndroidView(context: Context?, messenger: BinaryMessenger, viewId: Int, args: Any?) : PlatformView {

    private val textView = TextView(context)

    init {
        textView.text = "这是AndroidView"
    }

    override fun getView(): View {
        return textView
    }

    override fun dispose() {
    }
}

二、注册AndroidView

1、创建继承PlatformViewFactory的AndroidFactory

/**
 * messenger   flutter与原生通讯需要该参数
 */
class AndroidFactory(val messenger: BinaryMessenger): PlatformViewFactory(StandardMessageCodec.INSTANCE) {

    override fun create(context: Context?, viewId: Int, args: Any?): PlatformView {
        return AndroidView(context, messenger, viewId, args)
    }

}

2、创建继承FlutterPlugin的AndroidPlugin

class AndroidPlugin : FlutterPlugin{

    override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        //这里“AndroidView”要和flutter中创建的AndroidView的viewType属性值一致
        binding.platformViewRegistry
                .registerViewFactory("AndroidView", AndroidFactory(binding.binaryMessenger))
    }

    override fun onDetachedFromEngine(binding: FlutterPlugin.FlutterPluginBinding) {

    }
}

3、在MainActivity中添加AndroidPlugin

class MainActivity: FlutterActivity() {

    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        flutterEngine.plugins.add(AndroidPlugin())
    }
}

三、Flutter中嵌入AndroidView

class AndroidViewDemo extends StatelessWidget{
  @override
  Widget build(BuildCotext context) {
    return Scaffold(
      appBar: Appbar(),
      body: Center(
        child: AndroidView(
          viewType: 'AndroidView',
        ),
      )
    );  
  }
}

------------------------------------------------------------------------进阶----------------------------------------------------------------------------------

四、创建AndroidView时传参

1、flutter端修改

class AndroidViewDemo extends StatelessWidget{
  @override
  Widget build(BuildCotext context) {
    return Scaffold(
      appBar: Appbar(),
      body: Center(
        child: AndroidView(
          viewType: 'AndroidView',
          creationParams: {'initText': '这是flutter初始化传参'},
          creationParamsCode: StandardMessageCode(),//这里编码器要和PlatformViewFactory构造方法定义的解码器匹配
        ),
      )
    );  
  }
}

2、Android端修改

/**
 * messenger   flutter与原生通讯需要该参数
 * viewId      控件唯一标识
 * args        初始化参数
 */
class AndroidView(context: Context?, messenger: BinaryMessenger, viewId: Int, args: Any?) : PlatformView {

    private val textView = TextView(context)

    init {
        textView.text = "这是AndroidView"
        if (args is Map<*, *>){
            textView.text = args["initText"] as String
        }
    }

    override fun getView(): View {
        return textView
    }

    override fun dispose() {
    }
}

五、flutter向AndroidView发送数据

1、flutter端修改

class AndroidViewDemo extends StatefulWidget {
  
  @override
  State<StatefulWidget> createState() {
    return AndroidViewDemoState();
  }
}

class AndroidViewDemoState extends State<AndroidViewDemo>{
  MethodChannel methodChannel = MethodChannel("AndroidView");
  
  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Container(
          width: double.infinity,
          height: 60,
          child: AndroidView(
            viewType: 'AndroidView',
            creationParams: {'initText':  '这是flutter初始化传参'},
            creationParamsCodec: StandardMessageCodec(),
          ),
        ),
        RaisedButton(
          child: Text("向AndroidView传递参数"),
          onPressed: () {
            methodChannel
                .invokeMethod('setText', {'text': '这是flutter给AndroidView传参'});
          },
        ),
      ],
    );
  }
}

2、Android端修改

/**
 * messenger   flutter与原生通讯需要该参数
 * viewId      控件唯一标识
 * args        初始化参数
 */
class AndroidView(context: Context?, messenger: BinaryMessenger, viewId: Int, args: Any?) : PlatformView, MethodChannel.MethodCallHandler {

    private val textView = TextView(context)
    private val methodChannel = MethodChannel(messenger, "AndroidView")

    init {
        textView.text = "这是AndroidView"
        if (args is Map<*, *>){
            textView.text = args["initText"] as String
        }
        methodChannel.setMethodCallHandler(this)
    }

    override fun getView(): View {
        return textView
    }

    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        when {
            call.method == "setText" -> {
                //flutter向AndroidView发送数据
                val text = call.argument<String>("text")
                textView.text = text
            }
            else -> result.notImplemented()
        }
    }

    override fun dispose() {
    }
}

六、flutter从AndroidView获取数据

1、flutter端修改

class AndroidViewDemo extends StatefulWidget {
  
  @override
  State<StatefulWidget> createState() {
    return AndroidViewDemoState();
  }
}

class AndroidViewDemoState extends State<AndroidViewDemo>{
  MethodChannel methodChannel = MethodChannel("AndroidView");
  
  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Container(
          width: double.infinity,
          height: 60,
          child: AndroidView(
            viewType: 'AndroidView',
            creationParams: {'initText':  '这是flutter初始化传参'},
            creationParamsCodec: StandardMessageCodec(),
          ),
        ),
        RaisedButton(
          child: Text("向AndroidView传递参数"),
          onPressed: () {
            methodChannel
                .invokeMethod('setText', {'text': '这是flutter给AndroidView传参'});
          },
        ),
        RaisedButton(
          child: Text("从AndroidView获取参数"),
          onPressed: () async {
            var result = await methodChannel.invokeMethod('getText');
            setState(() {
              text = result['text'];
            });
          },
        ),
        Text("$text")
      ],
    );
  }
}

2、Android端修改

/**
 * messenger   flutter与原生通讯需要该参数
 * viewId      控件唯一标识
 * args        初始化参数
 */
class AndroidView(context: Context?, messenger: BinaryMessenger, viewId: Int, args: Any?) : PlatformView, MethodChannel.MethodCallHandler {

    private val textView = TextView(context)
    private val methodChannel = MethodChannel(messenger, "AndroidView")

    init {
        textView.text = "这是AndroidView"
        if (args is Map<*, *>){
            textView.text = args["initText"] as String
        }
        methodChannel.setMethodCallHandler(this)
    }

    override fun getView(): View {
        return textView
    }

    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        when {
            call.method == "setText" -> {
                //flutter向AndroidView发送数据
                val text = call.argument<String>("text")
                textView.text = text
            }
            call.method == "getText" -> {
                //flutter从AndroidView获取数据
                result.success(mapOf("text" to "这是从AndroidView获取参数"))
            }
            else -> result.notImplemented()
        }
    }

    override fun dispose() {
    }
}

七、页面多个相同的原生View通讯问题(多个AndroidView时发送数据只有最后一个收到)

方案:构建不同名称的name的MethodChannel

1、flutter端修改

class AndroidViewDemo extends StatefulWidget {
  
  @override
  State<StatefulWidget> createState() {
    return AndroidViewDemoState();
  }
}

class AndroidViewDemoState extends State<AndroidViewDemo>{
  var methodChannels = [];
  
  @override
  Widget build(BuildContext context) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: <Widget>[
        Container(
          width: double.infinity,
          height: 60,
          child: AndroidView(
            viewType: 'AndroidView',
            creationParams: {'initText':  '这是flutter初始化传参'},
            onPlatformViewCreated: (viewId){
              methodChannels.add(MethodChannel("AndroidView_$viewId"));
            },
            creationParamsCodec: StandardMessageCodec(),
          ),
        ),
        Container(
          width: double.infinity,
          height: 60,
          child: AndroidView(
            viewType: 'AndroidView',
            creationParams: {'initText':  '这是flutter初始化传参'},
            onPlatformViewCreated: (viewId){
              methodChannels.add(MethodChannel("AndroidView_$viewId"));
            },
            creationParamsCodec: StandardMessageCodec(),
          ),
        ),
        RaisedButton(
          child: Text("向第一个AndroidView传递参数"),
          onPressed: () {
            methodChannels[0]
                .invokeMethod('setText', {'text': '这是flutter给AndroidView传参'});
          },
        ),
        RaisedButton(
          child: Text("向第二个AndroidView传递参数"),
          onPressed: () {
            methodChannels[1]
                .invokeMethod('setText', {'text': '这是flutter给AndroidView传参'});
          },
        ),
        RaisedButton(
          child: Text("从AndroidView获取参数"),
          onPressed: () async {
            var result = await methodChannel.invokeMethod('getText');
            setState(() {
              text = result['text'];
            });
          },
        ),
        Text("$text"),
      ],
    );
  }
}

2、Android端修改

/**
 * messenger   flutter与原生通讯需要该参数
 * viewId      控件唯一标识
 * args        初始化参数
 */
class AndroidView(context: Context?, messenger: BinaryMessenger, viewId: Int, args: Any?) : PlatformView, MethodChannel.MethodCallHandler {

    private val textView = TextView(context)
    private val methodChannel = MethodChannel(messenger, "AndroidView_$viewId")

    init {
        textView.text = "这是AndroidView"
        if (args is Map<*, *>){
            textView.text = args["initText"] as String
        }
        methodChannel.setMethodCallHandler(this)
    }

    override fun getView(): View {
        return textView
    }

    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        when {
            call.method == "setText" -> {
                //flutter向AndroidView发送数据
                val text = call.argument<String>("text")
                textView.text = text
            }
            call.method == "getText" -> {
                //flutter从AndroidView获取数据
                result.success(mapOf("text" to "这是从AndroidView获取参数"))
            }
            else -> result.notImplemented()
        }
    }

    override fun dispose() {
    }
}

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值