Flutter WebView控制器问题:底部导航切换URL失效求助
问题原因分析
- WebViewController未正确获取:你的
WebViewContainer是无状态组件,且没有将内部的WebViewController暴露给父组件,导致controller变量始终为null,调用loadRequest自然无效。 - URL转换错误:直接将字符串强转为
Uri会报错,应该用Uri.parse()方法转换。 - 导航项与URL列表不匹配:底部导航只有2个选项,但你需要4个,同时
webViewList只有3个URL,数量不对应。
修正方案
1. 修改web_view_container.dart
将无状态组件改为有状态组件,并通过回调将WebViewController传递给父组件:
import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; class WebViewContainer extends StatefulWidget { final String initialUrl; final Function(WebViewController controller) onControllerCreated; const WebViewContainer({ required this.initialUrl, required this.onControllerCreated, super.key, }); @override State<WebViewContainer> createState() => _WebViewContainerState(); } class _WebViewContainerState extends State<WebViewContainer> { late WebViewController _controller; @override void initState() { super.initState(); _controller = WebViewController() ..setJavaScriptMode(JavaScriptMode.unrestricted) ..loadRequest(Uri.parse(widget.initialUrl)); widget.onControllerCreated(_controller); } @override Widget build(BuildContext context) { return WebViewWidget(controller: _controller); } }
2. 修改main.dart
更新导航项、URL列表,正确获取并使用WebViewController:
import 'package:flutter/material.dart'; import 'package:vertbaudet_webview/web_view_container.dart'; import 'package:webview_flutter/web_view_flutter.dart'; void main() => runApp( MaterialApp( debugShowCheckedModeBanner: false, home: const WebViewExample(), ), ); class WebViewExample extends StatefulWidget { const WebViewExample({super.key}); @override _WebViewExampleState createState() => _WebViewExampleState(); } class _WebViewExampleState extends State<WebViewExample> { int selectedIndex = 0; final List<String> webViewList = [ "https://google.com", "https://yahoo.com", "https://baidu.com", "https://www.vertbaudet.fr/", // 第四个URL,对应第四个导航项 ]; WebViewController? controller; @override Widget build(BuildContext context) { return Scaffold( bottomNavigationBar: BottomNavigationBar( items: const <BottomNavigationBarItem>[ BottomNavigationBarItem( icon: Icon(Icons.home), label: "首页", ), BottomNavigationBarItem( icon: Icon(Icons.business), label: "示例", ), BottomNavigationBarItem( icon: Icon(Icons.search), label: "搜索", ), BottomNavigationBarItem( icon: Icon(Icons.shopping_cart), label: "商城", ), ], currentIndex: selectedIndex, selectedItemColor: Colors.cyan, onTap: (i) { setState(() { selectedIndex = i; }); // 使用正确的Uri转换方式加载URL controller?.loadRequest(Uri.parse(webViewList[i])); }, ), appBar: AppBar( backgroundColor: const Color.fromRGBO(255, 255, 255, 1), toolbarHeight: 5, elevation: 0, ), body: WebViewContainer( initialUrl: webViewList[selectedIndex], onControllerCreated: (WebViewController c) { controller = c; }, ), ); } }
关键改动说明
- 将
WebViewContainer改为有状态组件,在initState中初始化WebViewController,并通过回调传递给父组件。 - 修正了URL转换方式,使用
Uri.parse()替代错误的强转。 - 补充了第四个底部导航项和对应的URL,满足你4个选项的需求。
- 移除了无用的路由配置,直接将
WebViewExample设为首页。
内容的提问来源于stack exchange,提问作者Disinq
相关产品推荐
相关产品推荐

