Flutter 提供了一個平臺視圖(Platform View)的概念改橘。它提供了一種方法钱反,允許開發(fā)者在 Flutter 里面嵌入原生系統(tǒng)(Android 和 iOS)的視圖企孩,并加入到 Flutter 的渲染樹中湿弦,實(shí)現(xiàn)與 Flutter 一致的交互體驗(yàn)蹭秋。
首先,由作為客戶端的 Flutter此叠,通過向原生視圖的 Flutter 封裝類(在 iOS 和 Android 平臺分別是 UIKitView 和 AndroidView)傳入視圖標(biāo)識符纯续,用于發(fā)起原生視圖的創(chuàng)建請求;
然后灭袁,原生代碼側(cè)將對應(yīng)原生視圖的創(chuàng)建交給平臺視圖工廠(PlatformViewFactory)實(shí)現(xiàn)猬错;
最后,在原生代碼側(cè)將視圖標(biāo)識符與平臺視圖工廠進(jìn)行關(guān)聯(lián)注冊茸歧,讓 Flutter 發(fā)起的視圖創(chuàng)建請求可以直接找到對應(yīng)的視圖創(chuàng)建工廠倦炒。
flutter 端代碼
class DefaultPage extends StatefulWidget {
@override
? StatecreateState()=>DefaultState();
}
class DefaultState extends State {
late NativeViewController controller;
@override
? void initState() {
controller =NativeViewController();
super.initState();
}
@override
? Widget build(BuildContext context) {
return Scaffold(
backgroundColor:Colors.yellowAccent,
appBar:AppBar(title:Text("Default Page")),
body:Center(
child:Container(width:200, height:200,
child:SampleView27(controller:controller)),
),
floatingActionButton:
FloatingActionButton(child:Icon(Icons.change_history),
onPressed: ()=>controller.changeBackgroundColor())
);
}
}
class SampleView extends StatefulWidget {
const SampleView({
Key ? key,
required this.controller,
}) :super(key: key);
final NativeViewController controller;
@override
? StatecreateState() =>_SampleViewState();
}
class _SampleViewState extends State {
@override
? Widget build(BuildContext context) {
if (defaultTargetPlatform ==TargetPlatform.android) {
return AndroidView(
viewType:'SampleView',
onPlatformViewCreated:_onPlatformViewCreated,
);
}else {
return UiKitView(viewType:'SampleView',
onPlatformViewCreated:_onPlatformViewCreated
? ? ? );
}
}
_onPlatformViewCreated(int id)=>widget.controller.onCreate(id);
}
class NativeViewController {
late MethodChannel _channel;
onCreate(int id) {
print(id);
_channel =MethodChannel('samples.chenhang/native_views_$id');
}
changeBackgroundColor()async
? {
_channel.invokeMethod('changeBackgroundColor');
}
}
iOS端代碼?
?Info.plist 文件中增加一項(xiàng)配置
<dict>
? ? <key>io.flutter.embedded_views_preview</key>
? <true/>
</dict>
import Foundation
import Flutter
class PlatformTextViewFactory:NSObject,FlutterPlatformViewFactory {
var messenger:FlutterBinaryMessenger!
func create(withFrame frame:CGRect, viewIdentifier viewId: Int64, arguments args: Any?) ->FlutterPlatformView {
return PlatformTextView(frame,viewID:viewId,args: args, binaryMessenger: messenger)
}
func createArgsCodec(messenger: (NSObject&FlutterBinaryMessenger)?)-> FlutterMessageCodec&NSObjectProtocol {
returnFlutterStandardMessageCodec.sharedInstance()
}
@objc public init(messenger: (NSObject&FlutterBinaryMessenger)?) {
super.init()
self.messenger = messenger
}
}
import Foundation
import Flutter
import UIKit
class PlatformTextView:NSObject,FlutterPlatformView {
let frame:CGRect;
let viewId:Int64;
var text:String =""
var messenger:FlutterBinaryMessenger!
var _label = UILabel();
init(_ frame:CGRect,viewID: Int64,args :Any?, binaryMessenger: FlutterBinaryMessenger) {
self.frame = frame
self.viewId = viewID
self.messenger = binaryMessenger;
if(args is NSDictionary){
let dict = args as! NSDictionary
? ? ? ? ? ? self.text = dict.value(forKey: "text") as! String
}
}
func initMethodChannel(){
letchannel = FlutterMethodChannel.init(name:"samples.chenhang/native_views_\(viewId)",binaryMessenger: messenger);
channel.setMethodCallHandler({ [self]
(call: FlutterMethodCall, result: FlutterResult) ->Void in
? ? ? ? ? ? ? ? if(call.method =="changeBackgroundColor"){
_label.backgroundColor = UIColor.blue
? ? ? ? ? ? ? ? ? ? print("-------")
result(0)
}else{
_label.backgroundColor = UIColor.red
? ? ? ? ? ? ? ? ? ? result(FlutterMethodNotImplemented);
}
});
}
func view()-> UIView {
initMethodChannel()
print(self.text)
_label.text =self.text
_label.backgroundColor = UIColor.red
_label.textColor = UIColor.white
_label.frame =self.frame
? ? ? ? return_label
}
}
override func application(
_ application:UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) ->Bool {
GeneratedPluginRegistrant.register(with:self)
let registrar = self.registrar(forPlugin: "samples.chenhang/native_views")
let messenger = registrar!.messenger() as! (NSObject & FlutterBinaryMessenger)
let factory = PlatformTextViewFactory(messenger:messenger)
registrar!.register(factory, withId: "SampleView")
return super.application(application, didFinishLaunchingWithOptions:launchOptions)
}
}
android 端代碼
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.view.FlutterView;
import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugin.platform.PlatformViewFactory;
import android.view.*;
import android.content.*;
import android.graphics.Color;
import io.flutter.plugin.common.MessageCodec;
import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.plugin.common.BinaryMessenger;
import android.content.Intent;
import io.flutter.embedding.engine.FlutterEngine;
import androidx.annotation.NonNull;
import io.flutter.embedding.engine.plugins.shim.ShimPluginRegistry;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.StandardMessageCodec;
public class MainActivityextends FlutterActivity {
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
ShimPluginRegistry shimPluginRegistry =new ShimPluginRegistry(flutterEngine);
GeneratedPluginRegistrant.registerWith(flutterEngine);
PluginRegistry.Registrar registrar = shimPluginRegistry.registrarFor("samples.chenhang/native_views");
SampleViewFactory playerViewFactory =new SampleViewFactory(registrar.messenger());
registrar.platformViewRegistry().registerViewFactory("SampleView", playerViewFactory);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
? ? }
}
class SampleViewFactoryextends PlatformViewFactory {
private final BinaryMessenger messenger;
public SampleViewFactory(BinaryMessenger msger) {
super(StandardMessageCodec.INSTANCE);
messenger = msger;
}
@Override
public PlatformView create(Context context,int id, Object obj) {
return new SimpleViewControl(context, id, messenger);
}
}
class SimpleViewControlimplements PlatformView, MethodChannel.MethodCallHandler {
private final MethodChannel methodChannel;
private final View view;
public SimpleViewControl(Context context,int id, BinaryMessenger messenger) {
view =new View(context);
view.setBackgroundColor(Color.rgb(255,0,0));
methodChannel =new MethodChannel(messenger,"samples.chenhang/native_views_" + id);
methodChannel.setMethodCallHandler(this);
}
@Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
if (methodCall.method.equals("changeBackgroundColor")) {
view.setBackgroundColor(Color.rgb(0,0,255));
result.success(0);
}else {
result.notImplemented();
}
}
@Override
public View getView() {
return view;
}
@Override
public void dispose() {
}
}