美文网首页
webview_flutter 远程或本地网页JaveScrip

webview_flutter 远程或本地网页JaveScrip

作者: antcore | 来源:发表于2019-11-22 13:35 被阅读0次

完整实例代码 Gitee

flutter dependencies

dependencies:
  flutter:
    sdk: flutter
  webview_flutter: ^0.3.15+1
  fluttertoast: ^3.1.3
class _ComponentWebviewState extends State<ComponentWebview> {
  bool _loading = false;
  WebViewController _webViewController;
  @override
  void initState() {
    super.initState();
  }
  @override
  Widget build(BuildContext context) {
    //加载  远程网页 OR 本地网页
    var isRemote = widget.url.contains('http');
    return Stack(
      children: <Widget>[
        Scaffold(
          body: isRemote ? loadRemoteUrl() : loadAssetsUrl(),
          floatingActionButton: FloatingActionButton(
            onPressed: () {
              _webViewController
                  ?.evaluateJavascript(
                      'customeFunc("Flutter 调用 JS Time: ${DateTime.now().toUtc()}")')
                  ?.then((result) {
                // You can handle JS result here.
                print("customeFunc" + result);
              });
            },
            child: Text('调用JS'),
          ),
        ),
        //加载网页提示
        uiLoading()
      ],
    );
  }
  Widget uiLoading() {
    if (_loading)
      return Center(child:CircularProgressIndicator()) ;//Center(child: Icon(Icons.play_circle_filled));
    else
      return Container(height: 0.0, width: 0.0);
  }
  // 定义 网页中能够调用的 Flutter 方法
  JavascriptChannel jsChannelShowToast(BuildContext context) {
    return JavascriptChannel(
        name: 'flutterShowToast',
        onMessageReceived: (JavascriptMessage message) {
          Fluttertoast.showToast(
              msg: message.message,
              toastLength: Toast.LENGTH_SHORT,
              gravity: ToastGravity.CENTER,
              timeInSecForIos: 1,
              backgroundColor: Colors.red,
              textColor: Colors.white,
              fontSize: 16.0);
        });
  }
  ///JS和Flutter通信的Channel;
  /// js 调用 flutter 方法
  List<JavascriptChannel> _getWebViewJavascriptChannels() {
    return <JavascriptChannel>[
      jsChannelShowToast(context),
    ];
  }
  _navigationDelegateHandle(NavigationRequest request) {
    print('request.url =======> : ${request.url}');
    //路由委托(可以通过在此处拦截url实现JS调用Flutter部分);
    ///通过拦截url来实现js与flutter交互
    if (request.url.toLowerCase().startsWith('webviewflutterurl://')) {
      // Fluttertoast.showToast(msg:'JS调用了Flutter By navigationDelegate');
      print('blocking navigation to $request}');
      return NavigationDecision.prevent;
      ///阻止路由替换,不能跳转,因为这是js交互给我们发送的消息
    }
    return NavigationDecision.navigate;
    //允许路由替换
  }
  ///页面加载完成处理
  _onPageFinished(String url) async {
    // 获取当前加载页面的 title
    String title = await _webViewController.getTitle();
    widget.titleChandge(title);
    setState(() {
      _loading = false;
    });
    print('Page finished url ====> : $url');
    //添加一些 webview 初始化数据
    var jsonData = {'platform': Platform.isAndroid ? 'android' : 'ios'};
    var jsonDataString = jsonEncode(jsonData);
    print(jsonDataString);
    //通知网页服务器加载完成并触发加载完成事件
    _webViewController
        ?.evaluateJavascript(
            'triggerEventWebViewFlutterJSBridgeReady($jsonDataString)')
        ?.then((result) {
      print(result);
    });
  }
}

Remote 网页

  ///加载 远程 html
  Widget loadRemoteUrl() {
    return WebView(
        initialUrl: widget.url,
        javascriptMode: JavascriptMode.unrestricted,
        onWebViewCreated: (WebViewController webViewController) {
          setState(() { _loading = true; }); 
          _webViewController = webViewController;
        },
        javascriptChannels: _getWebViewJavascriptChannels().toSet(),
        navigationDelegate: (request) => _navigationDelegateHandle(request),
        onPageFinished: (url) => _onPageFinished(url));
  }

localhost 网页

需要引入

import 'dart:io';
import 'package:flutter/services.dart';
 
  ///加载 本地 html
  Widget loadAssetsUrl() {
    return FutureBuilder(
        future: _loadHtmlFile(),
        builder: (context, snapshot) => WebView(
            initialUrl: Uri.dataFromString(snapshot.data, mimeType: 'text/html',  encoding: Encoding.getByName('utf-8')) .toString(),
            javascriptMode: JavascriptMode.unrestricted,
            onWebViewCreated: (WebViewController webViewController) {
              setState(() { _loading = true; });
              _webViewController = webViewController;
            },
            javascriptChannels: _getWebViewJavascriptChannels().toSet(),
            navigationDelegate: (request) => _navigationDelegateHandle(request),
            onPageFinished: (url) => _onPageFinished(url)));
  }
  /// 加载本地 HTML 文件
  Future<String> _loadHtmlFile() async {
    return await rootBundle.loadString(widget.url);
  }

网页部分

<section style="text-align: center;">
        <div id="content"> </div>
        <button id="btnFlutterFunc">jquery调用Flutter</button> <hr>
        <button onclick="showToast()">原生Js调用Flutter</button> <hr>
        <a href="webviewflutterurl://fff?p1=123&p2=321">连接拦截 GO ==> :webviewflutterurl://fff?p1=123&p2=321</a>
    </section>
    <script type="text/javascript" src="./jquery.min.js"></script>
    <script type="text/javascript">
        function showToast(message) {
            flutterShowToast.postMessage(message || "JS调用了Flutter");
        }
        // 首先需要提前定义好事件,并且注册相关的EventListener
        var eventWebViewFlutterJSBridgeReady = new CustomEvent('webViewFlutterJSBridgeReady', {
            detail: { 
                //平台 android OR ios
                platform: '' 
            },
        });
        function triggerEventWebViewFlutterJSBridgeReady(jsonData) {
            console.log(JSON.stringify(jsonData))
            setTimeout(function () {
                eventWebViewFlutterJSBridgeReady.detail.platform = jsonData.platform
                if (window.dispatchEvent)
                    window.dispatchEvent(eventWebViewFlutterJSBridgeReady);
                else
                    window.fireEvent(eventWebViewFlutterJSBridgeReady);
            }, 200)
            return '已触发事件:webViewFlutterJSBridgeReady:platform:${jsonData.platform}';
        }
        window.addEventListener('webViewFlutterJSBridgeReady', function (event) {
            console.log('触发:webViewFlutterJSBridgeReady');
        });
        window.addEventListener('webViewFlutterJSBridgeReady', function (event) {
            showToast('Js:CustomEvent:webViewFlutterJSBridgeReady'+JSON.stringify(event.detail));
        });
        function customeFunc(message) {
            document.getElementById("content").innerHTML = message;
            return 'customeFunc 调用完成'
        }
        $(function () {
            var elementContent = $('.content');
            var elementBtnFlutterFunc = $('#btnFlutterFunc');
            elementBtnFlutterFunc.unbind('click').bind('click', function () {
                showToast();  
            })
        })
    </script>

网页中加入 自定义事件 CustomEvent webViewFlutterJSBridgeReady
以便通知网页网页加载完成 在调用的时候初始化部分 信息 如 硬件平台信息 等

加载本地网页加载JQuery 还没研究透 ... 没找到方法

String title = 'webview title';
  @override
  Widget build(BuildContext context) {
    var url = 'https://www.baidu.com';
    url = 'http://www.baidu.com';
    url = 'http://192.168.2.65:9777/Content/static/webview_flutter.html';
    var now =new DateTime.now();
    url = '$url?t=${now.toUtc()}';
    // url = "assets/www/webview_flutter.html";
    return Scaffold(
      appBar: AppBar(title:Text(title)),
      body: ComponentWebview(url: url,titleChandge: (value){
        print(value);
        setState(() {
          title = value;
        });
      }),
    );
  }

关于WebView_Fultter 启用 http 请看 上一篇

相关文章

网友评论

      本文标题:webview_flutter 远程或本地网页JaveScrip

      本文链接:https://www.haomeiwen.com/subject/muofwctx.html