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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 20:24:56