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

Flutter:如何通过滑动底部导航栏切换对应页面?

问题分析与解决方案

你的代码存在两处关键问题:一是误用了DefaultTabController却自行维护_screen状态,DefaultTabController本身会自动管理Tab的选中索引,不需要额外状态;二是TabBarView里的switch仅处理了case 0,导致无论滑动到哪个Tab都只返回同一个文本页面。

下面提供几种可行的实现方式,按需选择:


方式一:直接使用页面列表(最简洁)

适合页面结构规整、无需复杂初始化逻辑的场景,通过创建与tabNames顺序一一对应的页面组件列表,直接在TabBarView中返回对应页面,代码清爽易维护。

修改后完整代码

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

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

const List<String> tabNames = <String>[
  'Reports', 'Reminders', 'Savings', 'Subscription', 'BudgetPlanner',
];

// 定义各个独立页面组件
class ReportsPage extends StatelessWidget {
  const ReportsPage({super.key});
  @override
  Widget build(BuildContext context) {
    return const Center(child: Text('Reports Page'));
  }
}

class RemindersPage extends StatelessWidget {
  const RemindersPage({super.key});
  @override
  Widget build(BuildContext context) {
    return const Center(child: Text('Reminders Page'));
  }
}

class SavingsPage extends StatelessWidget {
  const SavingsPage({super.key});
  @override
  Widget build(BuildContext context) {
    return const Center(child: Text('Savings Page'));
  }
}

class SubscriptionPage extends StatelessWidget {
  const SubscriptionPage({super.key});
  @override
  Widget build(BuildContext context) {
    return const Center(child: Text('Subscription Page'));
  }
}

class BudgetPlannerPage extends StatelessWidget {
  const BudgetPlannerPage({super.key});
  @override
  Widget build(BuildContext context) {
    return const Center(child: Text('BudgetPlanner Page'));
  }
}

class _MyHomePageState extends State<MyHomePage> {
  // 页面列表与tabNames顺序严格对应
  final List<Widget> _pages = const [
    ReportsPage(),
    RemindersPage(),
    SavingsPage(),
    SubscriptionPage(),
    BudgetPlannerPage(),
  ];

  @override
  Widget build(BuildContext context) {
    return DefaultTabController(
      length: tabNames.length,
      child: Scaffold(
        appBar: const AppBar(title: Text('Navigation example')),
        body: TabBarView(children: _pages),
        bottomNavigationBar: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.stretch,
          children: [
            Material(
              color: Theme.of(context).primaryColor,
              child: const TabBar(
                isScrollable: true,
                tabs: [
                  Tab(text: 'REPORTS'),
                  Tab(text: 'REMINDERS'),
                  Tab(text: 'SAVINGS'),
                  Tab(text: 'SUBSCRIPTION'),
                  Tab(text: 'BUDGETPLANNER'),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }
}

方式二:使用switch语句(适合复杂页面场景)

如果每个页面需要单独初始化逻辑、传递不同参数,用switch根据索引返回对应页面会更灵活。

修改TabBarView部分代码

body: TabBarView(
  children: List.generate(tabNames.length, (index) {
    switch(index) {
      case 0: return const ReportsPage();
      case 1: return const RemindersPage();
      case 2: return const SavingsPage();
      case 3: return const SubscriptionPage();
      case 4: return const BudgetPlannerPage();
      default: return const Center(child: Text('Unknown Page'));
    }
  }),
),

方式三:使用映射表(适合大量页面场景)

当页面数量较多时,用Map映射索引与页面,维护起来更便捷:

实现代码

// 定义页面映射表
final Map<int, Widget> _pageMap = {
  0: const ReportsPage(),
  1: const RemindersPage(),
  2: const SavingsPage(),
  3: const SubscriptionPage(),
  4: const BudgetPlannerPage(),
};

// TabBarView部分
body: TabBarView(
  children: List.generate(tabNames.length, 
    (index) => _pageMap[index] ?? const Center(child: Text('Unknown Page'))
  ),
),

内容的提问来源于stack exchange,提问作者User G Amsterdam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 00:20:51