Flutter中webview_flutter 4.0.2实现WebView内链接跳转求助
解决webview_flutter 4.0.2中WebView内部链接无法跳转的问题
你的代码缺少对WebView导航请求的处理逻辑,同时JavaScript模式启用时机有误,导致内部链接无法正常跳转。按以下步骤修改即可解决:
1. 配置导航请求回调
在setNavigationDelegate中添加onNavigationRequest回调,明确允许链接的跳转请求:
..setNavigationDelegate(NavigationDelegate( onPageFinished: (_) { updateHeight(); }, onNavigationRequest: (request) { // 允许所有链接在WebView内跳转,也可根据URL规则过滤特定链接 return NavigationDecision.navigate; }, ))
2. 调整JavaScript模式启用时机
必须在加载HTML之前启用JavaScript模式,否则WebView无法解析页面中的交互逻辑(包括链接跳转):
将await _controller.setJavaScriptMode(JavaScriptMode.unrestricted);移到loadHtmlString执行前。
3. 可选:区分内部/外部链接跳转
如果需要让外部链接跳转到系统浏览器,可修改onNavigationRequest逻辑(需额外引入url_launcher包):
onNavigationRequest: (request) { if (request.url.startsWith('http://your-internal-domain') || request.url.startsWith('https://your-internal-domain')) { // 内部链接在WebView内跳转 return NavigationDecision.navigate; } else { // 外部链接打开系统浏览器 // await launchUrl(Uri.parse(request.url)); return NavigationDecision.prevent; } },
修改后的完整代码
import 'dart:io'; import 'dart:ui'; import 'package:flutter/material.dart'; import 'package:flutter_html/flutter_html.dart'; import 'package:webview_flutter/webview_flutter.dart'; class MyWidget extends StatefulWidget { final MyWidgetModel model; const MyWidget({Key? key, required this.model}) : super(key: key); @override State<MyWidget> createState() => _MyWidgetState(); } class _MyWidgetState extends State<MyWidget> { late final WebViewController _controller; double webViewHeight = 10; bool loading = true; @override void initState() { super.initState(); _controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) // 提前启用JavaScript ..setNavigationDelegate(NavigationDelegate( onPageFinished: (_) { updateHeight(); }, onNavigationRequest: (request) { // 允许所有链接在WebView内跳转 return NavigationDecision.navigate; }, )); initWebView(); } void initWebView() async { String htmlString = ''; final startIndex = widget.model.page?.indexOf('<head>') ?? -1; if (startIndex > -1) { htmlString = widget.model.page!; } else { htmlString = ''' <!DOCTYPE html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0"> </head> <body> ${widget.model.page ?? ''} </body> </html> '''; } await _controller.loadHtmlString(htmlString); _controller.enableZoom(true); } void updateHeight() async { final screenHeight = MediaQuery.of(context).size.height; final bottomPadding = MediaQueryData.fromWindow(window).padding.bottom; final topPadding = MediaQueryData.fromWindow(window).padding.top; const appBarHeight = 84; final bottomBarPadding = Platform.isIOS ? 70 : 90; final minimumHeight = screenHeight - bottomBarPadding - bottomPadding - topPadding - appBarHeight; webViewHeight = minimumHeight; WidgetsBinding.instance.addPostFrameCallback((timeStamp) { setState(() { loading = false; }); }); } @override Widget build(BuildContext context) { if (widget.model.description == 'web_view') { return Container( constraints: BoxConstraints(minHeight: 0, maxHeight: webViewHeight), child: Stack( children: [ WebViewWidget( controller: _controller, ), if (loading) const Positioned.fill( child: CircularProgressIndicator( )) ], ), ); } // 补充默认返回值,避免编译错误 return const SizedBox.shrink(); } }
额外说明
- 确保HTML中的链接为标准
<a href="xxx">格式,无自定义JS阻止跳转的逻辑 - 页面内锚点跳转(如
#section)无需额外配置,WebView会自动处理
内容的提问来源于stack exchange,提问作者Tux Ficus Mercury
相关产品推荐
相关产品推荐

