1. 主页面(BottomNavBarPage)
  • 用 _currentBarIndex 记录当前选中的导航索引(默认 0,即首页)。
  • 用 IndexedStack 管理 4 个页面,通过 _currentBarIndex 控制显示哪个页面(比如索引 1 就显示 NodePage)。
  • 底部导航栏用 CustomNavigationBar 组件,传递当前索引和点击回调。
2. 底部导航栏(CustomNavigationBar)
  • 定义了 4 个导航项(NavItem),每个包含标题、图标、是否选中(isHighlighted)。
  • 通过 Row 横向排列 4 个导航项,每个占满屏幕宽度的 1/4(Expanded 组件实现)。
  • 点击导航项时,触发 onTap 回调,更新 _currentBarIndex 切换页面。
3. 导航项样式(选中 / 未选中)
  • 未选中状态_buildIconContainer):灰色图标,无背景。
  • 选中状态_buildHighlightedIconContainer):白色图标,带渐变绿色椭圆形背景(有边框),文字也变为亮绿色。
  • 通过 isHighlighted 判断状态,动态切换样式。

示例代码

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '底部导航栏示例',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: const BottomNavigationExample(),
    );
  }
}

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

  @override
  State<BottomNavigationExample> createState() => _BottomNavigationExampleState();
}

class _BottomNavigationExampleState extends State<BottomNavigationExample> {
  // 当前选中的索引
  int _currentIndex = 0;

  // 导航对应的页面
  final List<Widget> _pages = [
    const HomePage(),
    const ExplorePage(),
    const ProfilePage(),
  ];

  // 导航项配置
  final List<BottomNavigationBarItem> _navItems = [
    const BottomNavigationBarItem(
      icon: Icon(Icons.home),
      label: '首页',
      // 可选:设置选中时的图标
      activeIcon: Icon(Icons.home_filled),
    ),
    const BottomNavigationBarItem(
      icon: Icon(Icons.explore),
      label: '发现',
      activeIcon: Icon(Icons.explore_outlined),
    ),
    const BottomNavigationBarItem(
      icon: Icon(Icons.person),
      label: '我的',
      activeIcon: Icon(Icons.person_2),
    ),
  ];

  // 切换导航项
  void _onItemTapped(int index) {
    setState(() {
      _currentIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      // 根据当前索引显示对应的页面
      body: _pages[_currentIndex],
      // 底部导航栏
      bottomNavigationBar: BottomNavigationBar(
        // 当前选中的索引
        currentIndex: _currentIndex,
        // 点击事件
        onTap: _onItemTapped,
        // 导航项
        items: _navItems,
        // 选中时的颜色
        selectedItemColor: Colors.blue,
        // 未选中时的颜色
        unselectedItemColor: Colors.grey,
        // 选中时的文字大小
        selectedFontSize: 12,
        // 未选中时的文字大小
        unselectedFontSize: 12,
        // 导航栏类型:fixed表示导航项固定大小
        type: BottomNavigationBarType.fixed,
        // 背景颜色
        backgroundColor: Colors.white,
        // 阴影效果
        elevation: 8,
      ),
    );
  }
}

// 首页
class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text(
        '首页',
        style: TextStyle(fontSize: 24),
      ),
    );
  }
}

// 发现页
class ExplorePage extends StatelessWidget {
  const ExplorePage({super.key});

  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text(
        '发现',
        style: TextStyle(fontSize: 24),
      ),
    );
  }
}

// 我的页
class ProfilePage extends StatelessWidget {
  const ProfilePage({super.key});

  @override
  Widget build(BuildContext context) {
    return const Center(
      child: Text(
        '我的',
        style: TextStyle(fontSize: 24),
      ),
    );
  }
}

状态更新:点击导航项时修改索引

void _onItemTapped(int index) {
  setState(() {
    _currentIndex = index; // 更新选中索引
  });
}

// 绑定到 BottomNavigationBar
BottomNavigationBar(
  onTap: _onItemTapped, // 点击时触发索引更新
  currentIndex: _currentIndex, // 告诉组件当前选中哪个索引
  // ...
)

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐