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中。