Flutter项目中添加Webview(七)JavaScript求值

1,124 阅读1分钟

WebViewController可以在当前页面的上下文中对JavaScript表达式求值。对JavaScript求值有两种不同的方法:

  • 对于不返回值的JavaScript代码,使用runJavaScript
  • 对于返回值的JavaScript代码,使用runJavaScriptReturningResult.

如果需要启用JavaScript,需要配置WebView小部件,并 将javaScriptMode属性设置为JavascriptMode.unrestricted。默认情况下,javascriptMode设置为JavascriptMode.disabled

废话不多说,上代码:

class _WebViewStackState extends State<WebViewStack> {
    var loadingPercentage = 0;
    
    @override
    Widget build(BuildContext context) {
        return Stack(
            children: [
                WebView(
                    initialUrl: 'https://flutter.dev',
                    onWebViewCreated: (url) {
                        widget.controller.complete(webViewController);
                    },
                    onPageStarted: (url) {
                        setState(() {
                            loadingPercentage = 0;
                        });
                    },
                    onProgress: (progress) {
                        setState(() {
                            loadingPercentage = progress;
                        });
                    },
                    onPageFinished: (url) {
                        setState(() {
                            loadingPercentage = 100;
                        });
                    },
                    navigatioonDelegate: (navigation) {
                        final host = Uri.parse(navigation.url).host;
                        if (host.contains('youtube.com')) {
                            ScaffoldMessenger.of(context).showSnackBar(
                                SnackBar(
                                    content: Text(
                                        'Blocking navigation to $host'
                                    ),
                                ),
                            );
                            return NavigationDecision.prevent;
                        }
                        return NavigationDecision.navigate;
                    },
                    javascriptMode: JavascriptMode.unrestricted, // Add this line
                ),
                if (loadingPercentage < 100)
                    LinearProgressIndicator(
                        value: loadingPercentage / 100.0,
                    ),
            ],
        );
    }
}

现在,WebView可以执行JavaScript,可以向菜单中添加一个选项,以使用runJavaScriptReturningResult方法。

enum _menuOptions {
    navigationDelegate,
    userAgent, // Add this line
}

class Menu extends StatelessWidget {
    const Menu({required this.controller, Key? key}) : super(key: key);
    
    final Completer<WebViewController> controller;
    
    @override
    Widget build(BuildContext context) {
        return FutureBuilder<WebViewController>(
            future: controller.future,
            builder: (context, controller) {
                return PopupMenuButton<_MenuOptions>(
                    onSelected: (value) async {
                        switch(value) {
                            case: _MenuOptions.navigationDelegatte:
                                controller.data!.loadUrl('https://youtube.com');
                                break;
                            // Add from here ...
                            case _MenuOptions.userAgent:
                                final userAgent = await controller.data!.runJavascriptReturningResult('navigator.userAgent');
                                ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(userAgent),));
                                break;
                                // ... to here
                        }
                    },
                    itemBuilder: (context) => [
                        const PopupMenuItem<_MenuOptions>(
                            value: _MenuOptions.navigationDelegate,
                            child: Text('Navigate to Yooutube'),
                        ),
                        // Add from here...
                        const PopupMenuItem<_MenuOptions>(
                            value: _MenuOptions.userAgent,
                            child: Text('Show user-agent'),
                        ),
                        // ... to here
                    ],
                );
            }
        );
    }
}

当你点击"Show user-agent"(显示用户代理)菜单选项后,执行JavaScript表达式navigator.userAgent的结果将显示在SnackBar中。

ezgif.com-gif-maker.gif