在实际开发中,我们会遇到没有现成的 flutter 插件或者组件不满足要求的情况下,这个时候我们有以下两种方式可以实现:
- 根据 Flutter 插件机制自定义实现 Flutter 插件,一般用于一些特定简单双平台组件
- 使用 Flutter 提供的 PlatformView 组件封装现有 Native 组件给 Flutter 使用,一般用于复用已有的 Native 组件,比如 地图,WebView,视频播放, 分享等等
Flutter PlatformView
PlatformView是 flutter 官方提供的一个可以直接使用 Android 和 iOS 平台原生 View 组件。
- Android 平台:AndroidView
- iOS 平台:UiKitView
下面就通过使用 Native WebView 组件来阐述如何使用 PlatformView
Flutter 代码
@override
Widget build(BuildContext context) {
if (Platform.isAndroid) {
return AndroidView(
viewType: 'WebView',
creationParams: {
"url": "https://pub.dev",
},
creationParamsCodec: new StandardMessageCodec(),
);
}
if (Platform.isIOS) {
return UiKitView(
viewType: 'WebView',
creationParams: {
"url": "https://pub.dev",
},
creationParamsCodec: new StandardMessageCodec(),
);
}
return Center(
child: Text("coming soon"),
);
}
Android 平台实现
实现步骤:
- 继承 PlatformViewFactory ,实现 create 方法
public class WebViewPlatformView extends PlatformViewFactory {
private WebView webView;
private String url;
public WebViewPlatformView(MessageCodec<Object> createArgsCodec) {
super(createArgsCodec);
}
@Override
public PlatformView create(Context context, int i, Object o) {
Map<String, String> map = (HashMap<String, String>)o;
url = map.get("url");
webView = new WebView(context);
webView.setWebViewClient(new WebViewClient());
WebSettings webSettings = webView.getSettings();
webSettings.setAppCacheEnabled(true);
webSettings.setJavaScriptEnabled(true);
webSettings.setDomStorageEnabled(true);
webView.loadUrl(url);
return new PlatformView() {
@Override
public View getView() {
return webView;
}
@Override
public void dispose() {
}
};
}
}
- Native 注册 PlatformView 组件
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.StandardMessageCodec;
public class ViewRegistrant {
public static void registerWith(PluginRegistry registry) {
final String key = ViewRegistrant.class.getCanonicalName();
if (registry.hasPlugin(key)) return;
PluginRegistry.Registrar registrar = registry.registrarFor(key);
registrar.platformViewRegistry().registerViewFactory("WebView", new WebViewPlatformView(new StandardMessageCodec()));
}
}
// Activity 模式
public class NativeFlutterActivity extends FlutterActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
GeneratedPluginRegistrant.registerWith(this);
ViewRegistrant.registerWith(this);
}
}
// Fragment 模式
public class NativeFlutterFragment extends Fragment {
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
String route = getArguments().getString("route");
this.flutterView = Flutter.createView(getActivity(), getLifecycle(), route);
// fix black screen
this.flutterView.setZOrderOnTop(true);
// this.flutterView.setZOrderMediaOverlay(true);
this.flutterView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
// register view plugin
ViewRegistrant.registerWith(this.flutterView.getPluginRegistry());
return this.flutterView;
}
}
iOS 平台实现
实现步骤:
- 继承 PlatformViewFactory ,实现 create 方法
import Flutter
public class WebView : NSObject, FlutterPlatformView {
let frame: CGRect;
let viewId: Int64;
let args: Any?
init(_ frame: CGRect, viewId: Int64, args: Any?) {
self.frame = frame;
self.viewId = viewId;
self.args = args;
}
public func view() -> UIView {
let map = args as? [String: Any];
let mUrl = map?["url"] as? String;
let webView = UIWebView.init(frame: frame);
let url = URL(string: mUrl ?? "");
webView.loadRequest(URLRequest(url: url!));
return webView;
}
}
public class FlutterWebViewFactory: NSObject, FlutterPlatformViewFactory {
public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
return FlutterStandardMessageCodec.sharedInstance()
}
public func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
return WebView(frame, viewId: viewId, args: args);
}
}
- Native 注册 PlatformView 组件
import Flutter
public class ViewRegistrant {
public static func register(registry: FlutterPluginRegistry) -> Void {
registry.registrar(forPlugin: "Kitty").register(FlutterWebViewFactory(), withId: "WebView");
}
}