在实际开发中,我们会遇到没有现成的 flutter 插件或者组件不满足要求的情况下,这个时候我们有以下两种方式可以实现:
- 根据 Flutter 插件机制自定义实现 Flutter 插件,一般用于一些特定简单双平台组件
- 使用 Flutter 提供的 PlatformView 组件封装现有 Native 组件给 Flutter 使用,一般用于复用已有的 Native 组件,比如 地图,WebView,视频播放, 分享等等
Flutter PlatformView
PlatformView是 flutter 官方提供的一个可以直接使用 Android 和 iOS 平台原生 View 组件。
- Android 平台:AndroidView
- iOS 平台:UiKitView
下面就通过使用 Native WebView 组件来阐述如何使用 PlatformView
Flutter 代码
@overrideWidget 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);}@Overridepublic 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() {@Overridepublic View getView() {return webView;}@Overridepublic 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 {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);GeneratedPluginRegistrant.registerWith(this);ViewRegistrant.registerWith(this);}}// Fragment 模式public class NativeFlutterFragment extends Fragment {@Overridepublic 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 screenthis.flutterView.setZOrderOnTop(true);// this.flutterView.setZOrderMediaOverlay(true);this.flutterView.getHolder().setFormat(PixelFormat.TRANSLUCENT);// register view pluginViewRegistrant.registerWith(this.flutterView.getPluginRegistry());return this.flutterView;}}
iOS 平台实现
实现步骤:
- 继承 PlatformViewFactory ,实现 create 方法
import Flutterpublic 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 Flutterpublic class ViewRegistrant {public static func register(registry: FlutterPluginRegistry) -> Void {registry.registrar(forPlugin: "Kitty").register(FlutterWebViewFactory(), withId: "WebView");}}
