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

求助:在Flutter中实现特定样式的自定义底部导航栏

Flutter 实现带凸起中间按钮的底部导航栏

下面是实现你需要的底部导航栏的方案,完全基于Flutter原生组件,无需第三方包:

核心思路

  • 用BottomAppBar作为底部导航栏主体,通过shape属性设置中间圆形缺口,适配凸起的主按钮
  • 搭配FloatingActionButton作为中间凸起按钮,通过floatingActionButtonLocation定位到缺口位置
  • 自定义导航项的选中/未选中样式,匹配设计需求

完整代码示例

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: 'Bottom Nav Demo',
      theme: ThemeData(primarySwatch: Colors.blue),
      home: const BottomNavScreen(),
    );
  }
}

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

  @override
  State<BottomNavScreen> createState() => _BottomNavScreenState();
}

class _BottomNavScreenState extends State<BottomNavScreen> {
  // 当前选中的导航索引
  int _selectedIndex = 0;

  // 导航项数据:图标、文字(除中间按钮外)
  final List<Map<String, dynamic>> _navItems = [
    {'icon': Icons.home, 'label': '首页'},
    {'icon': Icons.search, 'label': '搜索'},
    {'icon': Icons.notifications, 'label': '通知'},
    {'icon': Icons.person, 'label': '我的'},
  ];

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

  // 中间按钮点击事件
  void _onCenterButtonPressed() {
    // 这里添加中间按钮的业务逻辑
    debugPrint('中间按钮被点击');
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('底部导航示例')),
      body: Center(
        child: Text('当前页面:${_navItems[_selectedIndex]['label']}'),
      ),
      // 中间凸起的主按钮
      floatingActionButton: FloatingActionButton(
        onPressed: _onCenterButtonPressed,
        backgroundColor: Colors.orange,
        child: const Icon(Icons.add, color: Colors.white),
        elevation: 4,
      ),
      // 设置按钮位置,卡在BottomAppBar的缺口里
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
      // 底部导航栏主体
      bottomNavigationBar: BottomAppBar(
        shape: const CircularNotchedRectangle(), // 中间圆形缺口
        color: Colors.white,
        elevation: 8,
        child: SizedBox(
          height: 60,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: [
              // 左侧两个导航项
              _buildNavItem(0),
              _buildNavItem(1),
              // 中间留空,给FloatingActionButton
              const SizedBox(width: 40),
              // 右侧两个导航项
              _buildNavItem(2),
              _buildNavItem(3),
            ],
          ),
        ),
      ),
    );
  }

  // 构建单个导航项
  Widget _buildNavItem(int index) {
    final isSelected = _selectedIndex == index;
    return InkWell(
      onTap: () => _onItemTapped(index),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(
            _navItems[index]['icon'],
            color: isSelected ? Colors.orange : Colors.grey,
            size: 24,
          ),
          const SizedBox(height: 4),
          Text(
            _navItems[index]['label'],
            style: TextStyle(
              color: isSelected ? Colors.orange : Colors.grey,
              fontSize: 12,
              fontWeight: isSelected ? FontWeight.bold : FontWeight.normal,
            ),
          ),
        ],
      ),
    );
  }
}

自定义调整说明

  • 修改中间按钮样式:直接调整FloatingActionButton的backgroundColor、child、elevation等属性
  • 调整导航项样式:修改_buildNavItem里的颜色、文字大小、字体粗细参数
  • 调整导航栏高度:修改SizedBox(height: 60)的数值
  • 自定义缺口形状:可以自定义NotchedShape替换CircularNotchedRectangle()

内容的提问来源于stack exchange,提问作者Emmanuel Nartey

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 02:45:22