【问题标题】:How to listen to events in flutter webview?如何在flutter webview中监听事件?
【发布时间】:2020-11-22 02:37:27
【问题描述】:

当用户单击 webview 中存在的按钮时,我想在我的 Flutter 应用中关闭 webview

这是显示网页视图的代码

class WebViewApp extends StatefulWidget {
  @override
  _WebViewAppState createState() => _WebViewAppState();
}

class _WebViewAppState extends State<WebViewApp> {
  @override
  Widget build(BuildContext context) {
    return  WebviewScaffold(url: 'https://google.com',
        appBar: AppBar(
          title: Text('Test'),
          centerTitle: true,
          backgroundColor: kBlue,
          leading: BackButton(
            onPressed: (){
              Router.navigator.pop();
            },
          )
        ),
      );
  }
}

【问题讨论】:

  • 显示您用于 webview 的 url,以及您希望在 webview 中按下哪个按钮来关闭它?
  • 假设我想检测用户是否点击了运动。

标签: flutter flutterwebviewplugin


【解决方案1】:

在 Webview 构造函数中使用 navigationDelegate 参数。

WebView(
  initialUrl: 'https://flutter.dev',
  navigationDelegate: (action) {
    if (action.url.contains('google.com')) {
      // Won't redirect url
      print('Trying to open google');
      Navigator.pop(context); 
      return NavigationDecision.prevent; 
    } else if (action.url.contains('youtube.com')) {
     // Allow opening url
      print('Trying to open Youtube');
      return NavigationDecision.navigate; 
    } else {
      return NavigationDecision.navigate; 
    }
  },
),

就是这样!

【讨论】:

    【解决方案2】:

    请检查以下步骤以在单击 WebView 中的按钮时获取触发器:

    • 添加webview plugin

      webview_flutter: ^0.3.22+1

    • pubspec.yaml中添加了资产的引用

       assets:   
          assets/about_us.html
      
    • 在 assets 文件夹中添加了 html 文件

    about_us.html

    <html>
    
    <head>
        <script type="text/javascript">
            function invokeNative() {
                MessageInvoker.postMessage('Trigger from Javascript code');
            }
        </script> </head>
    
    <body>
        <form>
            <input type="button" value="Click me!" onclick="invokeNative()" />
        </form> </body>
    
    </html>
    
    • 添加了加载 WebView 的代码。

    根据以下语句,您可以看到我正在加载一个 WebView 和 当我单击 WebView 中名为 Click me! 的按钮时 Flutter 中的 JavascriptChannel 将被调用,并显示一条消息“触发器 来自 Javascript 代码”

    import 'dart:convert';
    import 'package:flutter/material.dart'; 
    import 'package:flutter/services.dart'; 
    import 'package:webview_flutter/webview_flutter.dart';
    
    class WebViewApp extends StatefulWidget {
      WebViewApp({Key key, this.title}) : super(key: key);
      final String title;
      @override
      _WebViewAppState createState() => _WebViewAppState();
    }
    
    class _WebViewAppState extends State<WebViewApp> {
      WebViewController _controller;
      Future<void> loadHtmlFromAssets(String filename, controller) async {
        String fileText = await rootBundle.loadString(filename);
        controller.loadUrl(Uri.dataFromString(fileText,
                mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
            .toString());
      }
      Future<String> loadLocal() async {
        return await rootBundle.loadString('assets/about_us.html');
      }
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: Text(widget.title),
          ),
          body: FutureBuilder<String>(
            future: loadLocal(),
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return WebView(
                  initialUrl:
                      new Uri.dataFromString(snapshot.data, mimeType: 'text/html')
                          .toString(),
                  javascriptMode: JavascriptMode.unrestricted,
                  javascriptChannels: <JavascriptChannel>[
                    JavascriptChannel(
                        name: 'MessageInvoker',
                        onMessageReceived: (s) {
                        Scaffold.of(context).showSnackBar(SnackBar(
                           content: Text(s.message),
                        ));
                        }),
                  ].toSet(),
                );
              } else if (snapshot.hasError) {
                return Text("${snapshot.error}");
              }
              return CircularProgressIndicator();
            },
          ), // This trailing comma makes auto-formatting nicer for build methods.
        );
      }
    }
    

    正如您在代码中看到的,有一个JavascriptChannel,当用户单击 webview 中的按钮时,它会被调用。有一个密钥可以识别频道,在我的例子中是MessageInvoker

    希望这能解决问题...

    【讨论】:

    • 感谢您的回答。这个问题从技术上回答了这个问题。但我的意图是收听任何网站上的任何事件,而不仅仅是我添加的 html。
    • 据我所知,jschannel/jsinterface 是唯一可用于启用 b/w JavaScript 代码和客户端 Flutter 代码通信的选项。
    • 感谢这个很好的例子,但是当我尝试这个时,它在调试模式下工作正常,但在生产中它不工作。有什么想法吗?
    • @FirasNizam 它不应该依赖于构建类型。您是否在 prod &debug 中加载相同的网页?
    【解决方案3】:

    您可以通过查看网址WebView即将打开来收听点击:

    WebView(
      initialUrl: 'https://google.com',
      navigationDelegate: (request) {
        if (request.url.contains('mail.google.com')) {
          print('Trying to open Gmail');
          Navigator.pop(context); // Close current window
          return NavigationDecision.prevent; // Prevent opening url
        } else if (request.url.contains('youtube.com')) {
          print('Trying to open Youtube');
          return NavigationDecision.navigate; // Allow opening url
        } else {
          return NavigationDecision.navigate; // Default decision
        }
      },
    ),
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-25
      • 1970-01-01
      • 2023-03-24
      • 2019-05-06
      • 1970-01-01
      相关资源
      最近更新 更多