在实际开发中,我们会遇到没有现成的 flutter 插件或者组件不满足要求的情况下,这个时候我们有以下两种方式可以实现:

  • 根据 Flutter 插件机制自定义实现 Flutter 插件,一般用于一些特定简单双平台组件
  • 使用 Flutter 提供的 PlatformView 组件封装现有 Native 组件给 Flutter 使用,一般用于复用已有的 Native 组件,比如 地图,WebView,视频播放, 分享等等

Flutter PlatformView

PlatformView是 flutter 官方提供的一个可以直接使用 Android 和 iOS 平台原生 View 组件。

  • Android 平台:AndroidView
  • iOS 平台:UiKitView

下面就通过使用 Native WebView 组件来阐述如何使用 PlatformView

Flutter 代码

  1. @override
  2. Widget build(BuildContext context) {
  3. if (Platform.isAndroid) {
  4. return AndroidView(
  5. viewType: 'WebView',
  6. creationParams: {
  7. "url": "https://pub.dev",
  8. },
  9. creationParamsCodec: new StandardMessageCodec(),
  10. );
  11. }
  12. if (Platform.isIOS) {
  13. return UiKitView(
  14. viewType: 'WebView',
  15. creationParams: {
  16. "url": "https://pub.dev",
  17. },
  18. creationParamsCodec: new StandardMessageCodec(),
  19. );
  20. }
  21. return Center(
  22. child: Text("coming soon"),
  23. );
  24. }

Android 平台实现

实现步骤:

  • 继承 PlatformViewFactory ,实现 create 方法
  1. public class WebViewPlatformView extends PlatformViewFactory {
  2. private WebView webView;
  3. private String url;
  4. public WebViewPlatformView(MessageCodec<Object> createArgsCodec) {
  5. super(createArgsCodec);
  6. }
  7. @Override
  8. public PlatformView create(Context context, int i, Object o) {
  9. Map<String, String> map = (HashMap<String, String>)o;
  10. url = map.get("url");
  11. webView = new WebView(context);
  12. webView.setWebViewClient(new WebViewClient());
  13. WebSettings webSettings = webView.getSettings();
  14. webSettings.setAppCacheEnabled(true);
  15. webSettings.setJavaScriptEnabled(true);
  16. webSettings.setDomStorageEnabled(true);
  17. webView.loadUrl(url);
  18. return new PlatformView() {
  19. @Override
  20. public View getView() {
  21. return webView;
  22. }
  23. @Override
  24. public void dispose() {
  25. }
  26. };
  27. }
  28. }
  • Native 注册 PlatformView 组件
  1. import io.flutter.plugin.common.PluginRegistry;
  2. import io.flutter.plugin.common.StandardMessageCodec;
  3. public class ViewRegistrant {
  4. public static void registerWith(PluginRegistry registry) {
  5. final String key = ViewRegistrant.class.getCanonicalName();
  6. if (registry.hasPlugin(key)) return;
  7. PluginRegistry.Registrar registrar = registry.registrarFor(key);
  8. registrar.platformViewRegistry().registerViewFactory("WebView", new WebViewPlatformView(new StandardMessageCodec()));
  9. }
  10. }
  1. // Activity 模式
  2. public class NativeFlutterActivity extends FlutterActivity {
  3. @Override
  4. protected void onCreate(Bundle savedInstanceState) {
  5. super.onCreate(savedInstanceState);
  6. GeneratedPluginRegistrant.registerWith(this);
  7. ViewRegistrant.registerWith(this);
  8. }
  9. }
  10. // Fragment 模式
  11. public class NativeFlutterFragment extends Fragment {
  12. @Override
  13. public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
  14. String route = getArguments().getString("route");
  15. this.flutterView = Flutter.createView(getActivity(), getLifecycle(), route);
  16. // fix black screen
  17. this.flutterView.setZOrderOnTop(true);
  18. // this.flutterView.setZOrderMediaOverlay(true);
  19. this.flutterView.getHolder().setFormat(PixelFormat.TRANSLUCENT);
  20. // register view plugin
  21. ViewRegistrant.registerWith(this.flutterView.getPluginRegistry());
  22. return this.flutterView;
  23. }
  24. }

iOS 平台实现

实现步骤:

  • 继承 PlatformViewFactory ,实现 create 方法
  1. import Flutter
  2. public class WebView : NSObject, FlutterPlatformView {
  3. let frame: CGRect;
  4. let viewId: Int64;
  5. let args: Any?
  6. init(_ frame: CGRect, viewId: Int64, args: Any?) {
  7. self.frame = frame;
  8. self.viewId = viewId;
  9. self.args = args;
  10. }
  11. public func view() -> UIView {
  12. let map = args as? [String: Any];
  13. let mUrl = map?["url"] as? String;
  14. let webView = UIWebView.init(frame: frame);
  15. let url = URL(string: mUrl ?? "");
  16. webView.loadRequest(URLRequest(url: url!));
  17. return webView;
  18. }
  19. }
  20. public class FlutterWebViewFactory: NSObject, FlutterPlatformViewFactory {
  21. public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
  22. return FlutterStandardMessageCodec.sharedInstance()
  23. }
  24. public func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
  25. return WebView(frame, viewId: viewId, args: args);
  26. }
  27. }
  • Native 注册 PlatformView 组件
  1. import Flutter
  2. public class ViewRegistrant {
  3. public static func register(registry: FlutterPluginRegistry) -> Void {
  4. registry.registrar(forPlugin: "Kitty").register(FlutterWebViewFactory(), withId: "WebView");
  5. }
  6. }