Preface: change a transparent color or meaning hair article? Is it hydrology? 😡 don’t worry, we are a anti – title party! Of course I know it’s not worth mentioning to change a transparent background to the plugin. Given the current ecology of Flutter, the wheels often have to be made by the plugin itself, let alone the source code. But in this article, you will learn how to modify the official Flutter plug-ins and maintain them yourself. You will also learn how to build your own company’s own plugin library.

Why write this article

Continuing with the introduction above, I am writing this article because I changed the official plugin for Flutter, webview_flutter. The official Plugin for Flutter, all in oneMaking the warehouseOn the maintenance of each library and interrelated. [See below]

Therefore, how to change the function of Flutter is a secondary issue. How to independently modify the required Flutter plug-ins in the vast library of Flutter plug-ins and maintain them yourself is more important!! I think it’s important to share it with you.

Demand background

The reason for this change is that the background of Flutter WebView is always white and our theme is black. In this way, H5’s colleagues need to set a black background when H5 is embedded, and the white background will appear before the web page is loaded, which makes the experience very bad. If the background of the WebView can be set as transparent, H5 does not need to set the background color, which will improve the maintainability and experience, so the demand arises.

Implementation steps

  1. Clone the plugin repository from Github and use Android Studio to open the WebView folder separately. You can see that there are three plugins.

2. Change the main plug-in dependencies

In the webview directory of the main plug-in, yamL still depends on the plugins in pub, so we change the source code in other directories, yamL does not depend on the plugins at all, it will not take effect.

flutter:
  plugin:
    platforms:
      android:
        default_package: webview_flutter_android
      ios:
        default_package: webview_flutter_wkwebview

dependencies:
  flutter:
    sdk: flutter
  webview_flutter_platform_interface: ^ 1.0.0
  webview_flutter_android: ^ 2.0.13
  webview_flutter_wkwebview: ^ 2.0.13
Copy the code

So I’ll change the YAML dependency to a relative path first so that our changes to the code will take effect. Change the flutter pub get and follow the source code to enter the local source file, good👍🏻

  1. Start changing the code

In the Build method of the WebView, you can see the parameters of the construct passed in through webView.platform. build and determine if the platform returns the corresponding view.

/// webview_flutter/webview_flutter/lib/src/webview.dart
@override
  Widget build(BuildContext context) {
    return WebView.platform.build(
      context: context,
      onWebViewPlatformCreated: _onWebViewPlatformCreated,
      webViewPlatformCallbacksHandler: _platformCallbacksHandler,
      javascriptChannelRegistry: _javascriptChannelRegistry,
      gestureRecognizers: widget.gestureRecognizers,
      creationParams: _creationParamsfromWidget(widget),
    );
  }

  /// Returns the corresponding view based on the device type
  static WebViewPlatform get platform {
    if (_platform == null) {
      switch (defaultTargetPlatform) {
        case TargetPlatform.android:
          _platform = AndroidWebView();
          break;
        case TargetPlatform.iOS:
          _platform = CupertinoWebView();
          break;
        default:
          throw UnsupportedError(
              "Trying to use the default webview implementation for $defaultTargetPlatform but there isn't a default one"); }}return_platform! ; }/// Set the parameter, here I've added a parameter to transparentBackground, which is of type bool
CreationParams _creationParamsfromWidget(WebView widget) {
  return CreationParams(
    initialUrl: widget.initialUrl,
    webSettings: _webSettingsFromWidget(widget),
    javascriptChannelNames: _extractChannelNames(widget.javascriptChannels),
    userAgent: widget.userAgent,
    autoMediaPlaybackPolicy: widget.initialMediaPlaybackPolicy,
    transparentBackground: widget.transparentBackground,
  );
}
Copy the code

For Android, go to webview_android.dart in Webview_flutter_Android. Can see by introducing native AndroidView view, by identifying ‘plugins. Flutter. IO/webview’ match.

/// webview_flutter/webview_flutter_android/lib/webview_android.dart
return GestureDetector(
      onLongPress: () {},
      excludeFromSemantics: true,
      child: AndroidView(
        viewType: 'plugins.flutter.io/webview',
        onPlatformViewCreated: (int id) {
          if (onWebViewPlatformCreated == null) {
            return;
          }
          onWebViewPlatformCreated(MethodChannelWebViewPlatform(
            id,
            webViewPlatformCallbacksHandler,
            javascriptChannelRegistry,
          ));
        },
        gestureRecognizers: gestureRecognizers,
        layoutDirection: Directionality.maybeOf(context) ?? TextDirection.rtl,
        creationParams:
            MethodChannelWebViewPlatform.creationParamsToMap(creationParams),
        creationParamsCodec: const StandardMessageCodec(),
      ),
    );
Copy the code

Then go to the Android directory, find the corresponding FlutterWebView file, and determine whether to enable transparent background by obtaining params passed by methodcCannel. If true, set backgroundColor to transparent.

Ps: As you can see, native plug-ins are easy to write. As long as the methodChannel communicates, the Flutter layer passes in params, and the native layer gets the parameters and parses them. Note that data is transferred to strings, and even json string streams are often used. It also returns the native view, which returns the view of the PlatformViewFactory via the PlatformView binding identifier, which is also a string. The native code has to be written. In this sense, is Flutter really cross-platform? How important is an active open source community for Flutter? Worth thinking about!

The core code is to change the background color of wkWebview to transparent

/// webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m NSNumber* transparentEnabled = args[@"transparentBackground"]; NSLog(@"transparentBackground >>> %i", [transparentEnabled boolValue]); // Set background color to transparent if([transparentEnabled boolValue]){NSLog(@" Start setting background color "); _webView.opaque = NO; _webView.backgroundColor = UIColor.clearColor; }Copy the code

Key points: How to introduce it into the project and maintain it independently

Once the function is implemented, consider how to introduce it into our project. In the past, plug-ins developed by myself were usually imported through git repository, so I created a new GitHub repository and uploaded the webView directory as a whole. Join project Flutter pub get after surprise discovery, failed! The reason for this is that there is no YAML file in the root directory, which is an unqualified Plugin for Flutter. So we need to specify the root directory of the plug-in, using path to specify it in the WebView folder.

 # webview component
  webview_flutter:
    git:
      url: git://github.com/~~~/webview_flutter_enable_transparent.git
      ref: main
      path: webview_flutter # specify path
Copy the code

Keep getting, surprise again!! The reason is: relative path.. /XXXX could not find the corresponding plug-in, is this reasonable? This makes sense, because Flutter must keep your package size as small as possible. Since you specify a library to rely on, I will only download the corresponding library, not the whole git download. So when we use the relative path, we can’t find any other plug-ins in the root directory. The solution is to use Git to import plug-ins that webView’s YAMl files depend on

dependencies:
  flutter:
    sdk: flutter
  webview_flutter_platform_interface:
    git:
      url: https://github.com/~~~/webview_flutter_enable_transparent.git
      ref: main
      path: webview_flutter_platform_interface
  webview_flutter_android:
    git:
      url: https://github.com/~~~/webview_flutter_enable_transparent.git
      ref: main
      path: webview_flutter_android
  webview_flutter_wkwebview:
    git:
      url: https://github.com/~~~/webview_flutter_enable_transparent.git
      ref: main
      path: webview_flutter_wkwebview
Copy the code

Get again, it’s up and running, perfect! 👌 🏻

WebView(
  initialUrl: "xxxxx",
  javascriptMode: JavascriptMode.unrestricted,
  transparentBackground: true.)Copy the code

Write in the last

With this change to the plugin, the functionality is actually not that difficult. However, I think I have learned a lot about the changes to the official Flutter plugin and how to maintain it in my own Git. Similarly, would it be more reasonable for my company’s Plugin to be managed in a way similar to the official Flutter Plugin management? I think this is a must, quickly create a repository, follow the above way, build an internal plug-in library tour!

We learn and progress together!!