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

如何在Flutter Web平台中获取WebView的当前URL?

解决Flutter Web中获取WebView当前页面URL的问题

方案一:升级webview_flutter_web到最新稳定版

早期的webview_flutter_web: ^0.2.3+4确实缺少直接获取当前URL的API,升级到与webview_flutter主包同步的最新版本(比如webview_flutter: ^4.4.0及对应兼容的webview_flutter_web版本)后,可通过官方API实现需求:

  1. 更新pubspec.yaml依赖:
dependencies:
  webview_flutter: ^4.4.0
  webview_flutter_web: ^0.2.3+10 # 版本号可随主包自动匹配
  1. 实现代码示例:
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class WebViewUrlTracker extends StatefulWidget {
  const WebViewUrlTracker({super.key});

  @override
  State<WebViewUrlTracker> createState() => _WebViewUrlTrackerState();
}

class _WebViewUrlTrackerState extends State<WebViewUrlTracker> {
  late final WebViewController _controller;
  String _currentUrl = '';

  @override
  void initState() {
    super.initState();
    _controller = WebViewController()
      ..loadRequest(Uri.parse('https://example.com'))
      ..setNavigationDelegate(
        NavigationDelegate(
          // 页面开始加载时更新URL
          onPageStarted: (String url) => _updateUrl(url),
          // 页面加载完成时更新URL
          onPageFinished: (String url) => _updateUrl(url),
          // 拦截页面跳转请求,同步更新URL
          onNavigationRequest: (NavigationRequest request) {
            _updateUrl(request.url);
            return NavigationDecision.navigate;
          },
        ),
      );
  }

  // 主动获取当前URL的方法
  Future<void> _fetchCurrentUrl() async {
    final url = await _controller.currentUrl();
    if (url != null) _updateUrl(url);
  }

  void _updateUrl(String url) {
    if (mounted) {
      setState(() => _currentUrl = url);
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('当前URL: $_currentUrl')),
      body: WebViewWidget(controller: _controller),
      floatingActionButton: FloatingActionButton(
        onPressed: _fetchCurrentUrl,
        child: const Icon(Icons.refresh),
      ),
    );
  }
}

方案二:通过JavaScript交互手动监听(兼容旧版或第三方WebView包)

如果升级包仍无法满足需求,可直接利用Flutter Web与JS的通信能力,注入代码监听URL变化并同步到Flutter:

  1. 核心逻辑:

    • 向WebView注入JS,监听页面加载、前进后退、哈希变化等事件
    • URL变化时通过postMessage或JavaScriptChannel通知Flutter
    • 在Flutter中接收消息并更新当前URL
  2. 实现代码示例:

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:html' as html;

class JsBasedUrlTracker extends StatefulWidget {
  const JsBasedUrlTracker({super.key});

  @override
  State<JsBasedUrlTracker> createState() => _JsBasedUrlTrackerState();
}

class _JsBasedUrlTrackerState extends State<JsBasedUrlTracker> {
  late final WebViewController _controller;
  String _currentUrl = '';

  @override
  void initState() {
    super.initState();
    // 监听JS发送的消息
    html.window.addEventListener('message', (event) {
      final msg = (event as html.MessageEvent).data;
      if (msg is String && msg.startsWith('URL_UPDATE:')) {
        _updateUrl(msg.replaceFirst('URL_UPDATE:', ''));
      }
    });

    _controller = WebViewController()
      ..loadRequest(Uri.parse('https://example.com'))
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..runJavaScript('''
        // 发送当前URL到Flutter的方法
        function sendUrl() {
          window.parent.postMessage('URL_UPDATE:' + window.location.href, '*');
        }
        // 页面加载完成时发送初始URL
        window.addEventListener('load', sendUrl);
        // 监听浏览器前进后退
        window.addEventListener('popstate', sendUrl);
        // 监听哈希路由变化
        window.addEventListener('hashchange', sendUrl);
        // 拦截window.location.href跳转
        const originalHrefSetter = Object.getOwnPropertyDescriptor(window.location, 'href').set;
        Object.defineProperty(window.location, 'href', {
          set: function(val) {
            originalHrefSetter.call(this, val);
            setTimeout(sendUrl, 100); // 延迟确保URL已更新
          }
        });
      ''');
  }

  void _updateUrl(String url) {
    if (mounted) setState(() => _currentUrl = url);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text('当前URL: $_currentUrl')),
      body: WebViewWidget(controller: _controller),
    );
  }
}

注意事项:

  • 方案二中的JS代码需根据目标页面的路由机制调整,比如单页应用可能需要额外监听框架自带的路由事件(如React Router的history.listen)
  • 使用postMessage时建议指定具体的源(替换*),避免安全风险

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 08:02:32