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

Flutter中点击自定义底部导航栏如何实现页面切换

Flutter自定义底部导航栏页面切换实现方案

你已完成底部导航栏的UI交互与选中状态逻辑,补充页面映射与容器结构即可实现切换功能,完整修改代码如下:

import 'package:flutter/material.dart';

// 示例首页,可替换为你的实际页面内容
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: const Center(child: Text("首页", style: TextStyle(fontSize: 24))),
    );
  }
}

// 示例搜索页,可替换为你的实际页面内容
class SearchPage extends StatelessWidget {
  const SearchPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: const Center(child: Text("搜索", style: TextStyle(fontSize: 24))),
    );
  }
}

// 示例我的账户页,可替换为你的实际页面内容
class AccountPage extends StatelessWidget {
  const AccountPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: const Center(child: Text("我的账户", style: TextStyle(fontSize: 24))),
    );
  }
}

class NavBarController extends StatefulWidget {
  const NavBarController({Key? key}) : super(key: key);

  @override
  _NavBarControllerState createState() => _NavBarControllerState();
}

class _NavBarControllerState extends State<NavBarController> {
  int selectedIndex = 0;
  Color backgroundColor = Colors.white;

  // 页面列表,顺序和下方导航项顺序一一对应
  final List<Widget> pageList = const [
    HomePage(),
    SearchPage(),
    AccountPage(),
  ];

  List<NavigationItem> items = [
    NavigationItem(const Icon(Icons.home), const Text('首页'), Colors.blue),
    NavigationItem(const Icon(Icons.search), const Text('搜索'), Colors.blue),
    NavigationItem(const Icon(Icons.people), const Text('我的账户'), Colors.blue)
  ];

  Widget _buildItem(NavigationItem item, bool isSelected) {
    return AnimatedContainer(
      duration: const Duration(milliseconds: 200),
      height: double.maxFinite,
      width: isSelected ? 165 : 70,
      padding: const EdgeInsets.only(left: 20, right: 10),
      decoration: BoxDecoration(
          color: isSelected ? item.color : Colors.white,
          borderRadius: const BorderRadius.all(Radius.circular(50))),
      child: ListView(
        scrollDirection: Axis.horizontal,
        children: <Widget>[
          Row(
            crossAxisAlignment: CrossAxisAlignment.center,
            children: <Widget>[
              IconTheme(
                data: IconThemeData(
                  size: 24,
                  color: isSelected ? backgroundColor : Colors.grey,
                ),
                child: item.icon,
              ),
              Padding(
                padding: const EdgeInsets.only(left: 8),
                child: isSelected
                    ? DefaultTextStyle.merge(
                        style: TextStyle(color: backgroundColor),
                        child: item.title,
                      )
                    : Container(),
              )
            ],
          )
        ],
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 页面主体,使用IndexedStack保留页面切换状态
      body: IndexedStack(
        index: selectedIndex,
        children: pageList,
      ),
      // 自定义悬浮导航栏
      bottomNavigationBar: Container(
        height: 65,
        width: double.infinity,
        margin: const EdgeInsets.symmetric(vertical: 10, horizontal: 20),
        padding: const EdgeInsets.only(left: 8, top: 8, right: 8, bottom: 8),
        decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(50),
            color: backgroundColor,
            boxShadow: [
              BoxShadow(
                color: Colors.black.withOpacity(0.4),
                spreadRadius: 0.5,
                blurRadius: 10,
                offset: const Offset(0, 5),
              )
            ]),
        child: Row(
          mainAxisAlignment: MainAxisAlignment.spaceBetween,
          children: items.map((item) {
            var itemIndex = items.indexOf(item);
            return GestureDetector(
              onTap: () {
                setState(() {
                  selectedIndex = itemIndex;
                });
              },
              child: _buildItem(item, selectedIndex == itemIndex),
            );
          }).toList(),
        ),
      ),
    );
  }
}

class NavigationItem {
  final Icon icon;
  final Text title;
  final Color color;

  NavigationItem(this.icon, this.title, this.color);
}

主要修改说明

  • 新增了3个示例页面,你可以直接替换为自己的业务页面代码
  • 新增pageList列表存储页面对象,顺序和导航项保持一致即可自动对应
  • 采用IndexedStack承载页面,切换时会保留各页面的原有状态,不需要每次重建
  • 调整了布局结构,将自定义导航栏放入Scaffold的bottomNavigationBar属性,适配悬浮导航的展示效果

内容的提问来源于stack exchange,提问作者Saw Tha Wah

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 11:27:01