The status quo

There are two main plug-ins, Flutter_webview_plugin and webview_flutter. Flutter_webview_plugin is a third-party plugin that is fully documented and has the largest number of stars. But there are two major problems:

  • The Flutter method cannot be called in JS
  • You cannot intercept H5 before it enters a URL

So this article uses the official Webview_FLUTTER, which is currently in preview release and expects more features

Installing a plug-in

pubspec.yaml

Add webview_flutter to dependencies: ^0.3.13

Dependencies: webview_flutter: ^ 0.3.13Copy the code

info.list

Path: ios/Runner/info.list

<key>io.flutter.embedded_views_preview</key>
<string>YES</string>

<key>NSAppTransportSecurity</key>
<dict>
	<key>NSAllowsArbitraryLoads</key>
	<true/>
	<key>NSAllowsArbitraryLoadsInWebContent</key>
	<true/>
</dict>
Copy the code

use

Parameters in

Parameter names type The default value instructions
initialUrl String ‘ ‘
onWebViewCreated Function Called when the WebView is created
javascriptMode JavascriptMode JavascriptMode.disabled JS execution mode does not call by default
javascriptChannels Set Flutter can be invoked using javascriptChannel JS
navigationDelegate Function Intercept request
onPageFinished Function Page load complete call
gestureRecognizers Set gestures

scenario

Load a URL as easily as possible

WebView(
  initialUrl: "https://flutterchina.club/".// Whether JS execution mode allows JS execution
  javascriptMode: JavascriptMode.unrestricted
)
Copy the code

H5 calls flutter — JavascriptChannel

// Insert the global Toaster method into the h5 window
JavascriptChannel _toastJavascriptChannel(BuildContext context) {
  return JavascriptChannel(
    name: 'Toaster',
    onMessageReceived: (JavascriptMessage message) {
      print(message);
      Fluttertoast.showToast(
        msg: message.message
      );
    });
}

// register javascriptChannels with the Webview component
new WebView(
  ...
  javascriptChannels: <JavascriptChannel>[ //javascriptChannels is the intermodulation method provided by the API,
    _toastJavascriptChannel(context),
  ].toSet()
)

/ / js calls
Toaster.postMessage('js call flutter success!! ')
Copy the code

H5 calls flutter — navigationDelegate

new WebView(
  ...
  navigationDelegate: (NavigationRequest request) {
  // print('navigationDelegate: ${request.url}');
  if(request.url.indexOf('m=webview') > - 1) {
    String _url = helper.addUrlParam(request.url.replaceAll('&m=webview'.' '));
    Navigator.of(context).push(new MaterialPageRoute(builder: (_) {
      return Browser(
        title: ' '.url: _url
      );
    }));
    returnNavigationDecision.prevent; })Copy the code

Flutter call h5

// After the page is loaded, modify the Webview title
new WebView(
  ...
  onPageFinished: (url) {
    // Set the title
    _controller.evaluateJavascript("document.title").then((result){
      print(result); setState(() { widget.title = result; }); }); },)Copy the code

A complete component

import 'dart:convert';

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:fluttertoast/fluttertoast.dart';

import '.. /helper/index.dart' as helper;

class Browser extends StatefulWidget {
  String url;
  String title;

  Browser({this.url, this.title});

  @override
  _BrowserState createState() => _BrowserState();
}

class _BrowserState extends State<Browser> {
  dynamic _controller;

  @override
  void initState() {
    super.initState();
  }

  @override
  void dispose() {

    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    JavascriptChannel _toastJavascriptChannel(BuildContext context) {
      return JavascriptChannel(
        name: 'Toaster',
        onMessageReceived: (JavascriptMessage message) {
          print(message);
          Fluttertoast.showToast(
            msg: message.message
          );
        });
    }

    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Stack(
        children: <Widget>[
          new WebView(
            initialUrl: widget.url,
            javascriptMode: JavascriptMode.unrestricted,
            onWebViewCreated: (controller) {
              _controller = controller;
            },
            / * ** When the URL has 'm= webView ', a new webView is opened
* /
            navigationDelegate: (NavigationRequest request) {
              // print('navigationDelegate: ${request.url}');
              if(request.url.indexOf('m=webview') > - 1) {
                String _url = helper.addUrlParam(request.url.replaceAll('&m=webview'.' '));
                Navigator.of(context).push(new MaterialPageRoute(builder: (_) {
                  return Browser(
                    title: ' ',
                    url: _url
                  );
                }));
                return NavigationDecision.prevent;
              }

              return NavigationDecision.navigate;
            },
            onPageFinished: (url) {
              // Set the title
              _controller.evaluateJavascript("document.title").then((result){
                print(result);
                setState(() {
                  widget.title = result;
                });
              });

              // var a = '123';
              // print(a+1);

              // Test the method that flutter calls my page
              // _controller.evaluateJavascript("callJSFunc();" ).then((result){
              // // print('callJSFunc has called: $result');
              // });
            },
            javascriptChannels: <JavascriptChannel>[ //javascriptChannels is the intermodulation method provided by the API,_toastJavascriptChannel(context), ].toSet() ) ], ), ); }}Copy the code

todo

  • Access cordova
  • Obtain the network status of the device

Refer to the article

  • Flutter Hybrid Development (Interactive Communication)
  • Easy guide to Flutter WebView and JS interaction
  • Use WebView in Flutter