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

Flutter底部停靠导航栏实现咨询:中间按钮凸起固定

在Flutter中实现带凸起中间项的底部停靠导航栏

要实现你需要的这种底部停靠且中间项凸起的导航栏,核心是用BottomAppBar配合FloatingActionButton来完成,以下是具体实现步骤和完整代码:

核心思路

利用Scaffold的bottomNavigationBar属性设置带缺口的底部栏,再通过floatingActionButton放置中间的凸起按钮,同时指定按钮位置为居中停靠,让两者完美契合。

完整实现代码

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),
      home: const BottomNavPage(),
    );
  }
}

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

  @override
  State<BottomNavPage> createState() => _BottomNavPageState();
}

class _BottomNavPageState extends State<BottomNavPage> {
  // 当前选中的导航项索引(中间凸起项单独处理)
  int _selectedIndex = 0;

  // 页面列表,对应除中间项外的导航页面
  final List<Widget> _pages = const [
    Center(child: Text('首页')),
    Center(child: Text('消息')),
    Center(child: Text('我的')),
    Center(child: Text('设置')),
  ];

  // 处理底部导航项点击
  void _onItemTapped(int index) {
    setState(() {
      _selectedIndex = index;
    });
  }

  // 处理中间凸起按钮点击
  void _onMiddleButtonTap() {
    // 这里可以添加中间按钮的跳转逻辑,比如打开发布页面
    ScaffoldMessenger.of(context).showSnackBar(
      const SnackBar(content: Text('点击了中间凸起按钮')),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _pages[_selectedIndex],
      // 中间凸起的按钮
      floatingActionButton: FloatingActionButton(
        onPressed: _onMiddleButtonTap,
        elevation: 8, // 设置阴影,增强凸起效果
        backgroundColor: Colors.orange,
        child: const Icon(Icons.add, size: 30),
      ),
      // 指定按钮位置为居中停靠,嵌入BottomAppBar的缺口
      floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
      // 底部导航栏
      bottomNavigationBar: BottomAppBar(
        shape: const CircularNotchedRectangle(), // 创建中间的圆形缺口
        notchMargin: 6, // 缺口与按钮的间距
        color: Colors.white,
        elevation: 5,
        child: SizedBox(
          height: 60,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: <Widget>[
              // 第一个导航项
              IconButton(
                icon: Icon(
                  Icons.home,
                  color: _selectedIndex == 0 ? Colors.blue : Colors.grey,
                  size: 28,
                ),
                onPressed: () => _onItemTapped(0),
              ),
              // 第二个导航项
              IconButton(
                icon: Icon(
                  Icons.message,
                  color: _selectedIndex == 1 ? Colors.blue : Colors.grey,
                  size: 28,
                ),
                onPressed: () => _onItemTapped(1),
              ),
              // 中间留空,对应凸起按钮的位置
              const SizedBox(width: 40),
              // 第三个导航项
              IconButton(
                icon: Icon(
                  Icons.person,
                  color: _selectedIndex == 2 ? Colors.blue : Colors.grey,
                  size: 28,
                ),
                onPressed: () => _onItemTapped(2),
              ),
              // 第四个导航项
              IconButton(
                icon: Icon(
                  Icons.settings,
                  color: _selectedIndex == 3 ? Colors.blue : Colors.grey,
                  size: 28,
                ),
                onPressed: () => _onItemTapped(3),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

关键细节说明

  • BottomAppBar的shape: CircularNotchedRectangle()会自动生成适配圆形FloatingActionButton的缺口,如果你用方形按钮,可以换成AutomaticNotchedShape自定义缺口样式
  • 通过notchMargin调整缺口与凸起按钮的间距,让视觉效果更协调
  • 中间的SizedBox(width:40)是为了给凸起按钮留出位置,保证左右导航项对称
  • 可以通过调整FloatingActionButton的elevation、backgroundColor等属性,让凸起效果更贴合你的设计需求

内容的提问来源于stack exchange,提问作者Om Shivam

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 20:55:10