You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter WebView页面导航限制配置及onNavigationRequest失效问题

Flutter WebView 拦截所有URL跳转并返回应用的解决方案

问题核心

你当前使用的onNavigationRequest仅能拦截WebView的顶级导航请求(比如用户直接点击页面链接的跳转),但对于页面内JavaScript触发的跳转(如window.location.href、window.open)、iframe内部跳转等场景,该回调不会被触发,导致无法捕获所有URL。同时现有逻辑中部分拦截操作未返回NavigationDecision.prevent,会导致WebView仍尝试加载受限URL。


具体解决步骤

1. 修复现有onNavigationRequest逻辑

在拦截受限URL后,必须返回NavigationDecision.prevent来阻止WebView加载目标页面,同时完成应用内跳转:

onNavigationRequest: (NavigationRequest request) {
  if (request.url.startsWith('https://www.youtube.com/')) {
    return NavigationDecision.prevent;
  } else if (request.url.endsWith('page5')) {
    Navigator.pushNamedAndRemoveUntil(
        context, '/landingpage', (Route<dynamic> route) => false);
    return NavigationDecision.prevent; // 新增:阻止WebView加载
  } else if (request.url.startsWith('https://www.facebook.com/')) {
    Navigator.pushAndRemoveUntil(
        context,
        MaterialPageRoute(
            builder: (context) => verifyquickbuy(price: int.parse(widget.price))),
        (Route<dynamic> route) => false);
    return NavigationDecision.prevent; // 新增:阻止WebView加载
  }

  return NavigationDecision.navigate;
},

2. 注入JS脚本捕获所有跳转事件

通过注入自定义JavaScript,监听页面内所有可能的跳转行为(包括JS触发的跳转),再通过JavaScriptChannel将URL传递给Flutter端处理:

// 在WebViewController配置中添加以下代码
..addJavaScriptChannel(
  'UrlInterceptor',
  onMessageReceived: (JavaScriptMessage message) {
    final String url = message.message;
    // 复用之前的拦截逻辑
    if (url.startsWith('https://www.youtube.com/')) {
      // 阻止跳转
    } else if (url.endsWith('page5')) {
      Navigator.pushNamedAndRemoveUntil(context, '/landingpage', (route) => false);
    } else if (url.startsWith('https://www.facebook.com/')) {
      Navigator.pushAndRemoveUntil(
        context,
        MaterialPageRoute(builder: (context) => verifyquickbuy(price: int.parse(widget.price))),
        (route) => false,
      );
    }
  },
)
..runJavaScript('''
// 监听页面内所有链接点击
document.addEventListener('click', function(e) {
  let target = e.target;
  while (target && target.tagName !== 'A') {
    target = target.parentElement;
  }
  if (target && target.href) {
    UrlInterceptor.postMessage(target.href);
  }
});

// 监听window.location跳转
const originalHref = Object.getOwnPropertyDescriptor(window.location, 'href');
Object.defineProperty(window.location, 'href', {
  set: function(value) {
    UrlInterceptor.postMessage(value);
    originalHref.set.call(this, value);
  },
  get: function() {
    return originalHref.get.call(this);
  }
});

// 监听window.open跳转
const originalOpen = window.open;
window.open = function(url) {
  UrlInterceptor.postMessage(url);
  return originalOpen.apply(this, arguments);
};
''');

3. 避免重复创建WebViewController

检查getcontroller()方法,确保它不会在每次页面构建时重新创建WebViewController——控制器应仅在initState中初始化一次,否则之前配置的导航代理和JS通道会被覆盖失效。


内容的提问来源于stack exchange,提问作者CINO

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.01 01:35:16