Flutter多屏底部导航应用WebView子容器加载异常及页面兼容问询
问题:Flutter底部导航应用中WebView页面无法正常加载
我开发了一款带底部导航栏的Flutter多屏应用,其中一个页面需要用WebView作为子容器实现。目前应用整体运行正常,但WebView无法通过Container加载。我知道需要把Container替换为WebViewWidget,但不清楚修改后其他页面如何正常工作。
Dashboard Screen代码
import 'package:flutter/material.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:webview_flutter/webview_flutter.dart'; class DashboardScreen extends StatefulWidget { @override DashboardScreenState createState() => DashboardScreenState(); } class DashboardScreenState extends State<DashboardScreen> { int _selectedIndex = 0; void _onItemTapped(int index) { setState(() { getValues(); _selectedIndex = index; }); } late final WebViewController controller; @override void initState() { super.initState(); controller = WebViewController() ..loadRequest( Uri.parse('httpa://my-domain.com'), ); } // @override // Widget build(BuildContext context) { // return Stack( // children: [ // WebViewWidget( // controller: controller, // ) // ], // ); // } late var pages = [ new DashboardHomeFragment(controller: controller), new AccountFragment(), new PortfolioFragment(), new ProfileFragment(), ]; @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.transparent, // backgroundColor: const Color(0xff101324), appBar: AppBar( automaticallyImplyLeading: false, // backgroundColor: Color(0xFFB4C56C).withOpacity(0.0), backgroundColor: const Color(0xff00022e), elevation: 4, title: Image.asset( 'assets/images/logo-horizontal.png', height: 40, width: 150, ), centerTitle: true, ), body: Container(child: pages[_selectedIndex]), bottomNavigationBar: BottomNavigationBar( items: const <BottomNavigationBarItem>[ BottomNavigationBarItem( icon: Icon(Icons.home), label: 'Currency', ), BottomNavigationBarItem( icon: Icon(Icons.account_balance_wallet), label: 'Account', ), BottomNavigationBarItem( icon: Icon(Icons.work), label: 'Portfolio', ), BottomNavigationBarItem( icon: Icon(Icons.person), label: 'MyProfile', ), ], currentIndex: _selectedIndex, selectedItemColor: const Color(0xff3ACCE1), unselectedItemColor: Colors.white, showUnselectedLabels: true, backgroundColor: const Color(0xff2c2f40), type: BottomNavigationBarType.fixed, onTap: _onItemTapped, ), ); } }
Webview Screen代码
import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; class DashboardHomeFragment extends StatefulWidget { const DashboardHomeFragment({required this.controller, super.key}); final WebViewController controller; @override State<DashboardHomeFragment> createState() => DashboardHomeFragmentState(); } class DashboardHomeFragmentState extends State<DashboardHomeFragment> { @override Widget build(BuildContext context) { return Scaffold( backgroundColor: const Color(0xff0a0b37), body: Builder(builder: (BuildContext context) { widget.controller ..setNavigationDelegate( NavigationDelegate( onPageStarted: (url) { print('Page started loading: $url'); }, onPageFinished: (url) { print('Page finished loading: $url'); }, onNavigationRequest: (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; }, ), ) ..setJavaScriptMode(JavaScriptMode.unrestricted); return Text("data finding!"); }), ); } }
解决方案
1. 修复DashboardHomeFragment核心代码
将Fragment中的Scaffold移除(避免与父级DashboardScreen的Scaffold嵌套冲突),替换为WebViewWidget,并将controller的配置逻辑移到initState中(避免重复执行):
import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; class DashboardHomeFragment extends StatefulWidget { const DashboardHomeFragment({required this.controller, super.key}); final WebViewController controller; @override State<DashboardHomeFragment> createState() => DashboardHomeFragmentState(); } class DashboardHomeFragmentState extends State<DashboardHomeFragment> { @override void initState() { super.initState(); // 仅初始化时配置一次controller,避免build重复执行 widget.controller ..setNavigationDelegate( NavigationDelegate( onPageStarted: (url) { print('Page started loading: $url'); }, onPageFinished: (url) { print('Page finished loading: $url'); }, onNavigationRequest: (navigation) { final host = Uri.parse(navigation.url).host; if (host.contains('youtube.com')) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Blocking navigation to youtube.com'), ), ); return NavigationDecision.prevent; } return NavigationDecision.navigate; }, ), ) ..setJavaScriptMode(JavaScriptMode.unrestricted); } @override Widget build(BuildContext context) { return Container( color: const Color(0xff0a0b37), child: WebViewWidget(controller: widget.controller), ); } }
2. 修正DashboardScreen中的URL错误
将initState中的httpa://my-domain.com改为正确的https://my-domain.com,确保WebView能正常加载网页。
3. 其他页面的兼容性说明
你的其他页面(AccountFragment、PortfolioFragment、ProfileFragment)无需修改,只要它们本身是普通的Widget(而非嵌套Scaffold),就能在DashboardScreen的body: Container(child: pages[_selectedIndex])中正常显示,底部导航栏的切换逻辑不受影响。
内容的提问来源于stack exchange,提问作者Rizwan Patel
相关产品推荐
相关产品推荐

