flutter 3.x中实现底部导航凸起样式

一般实现需要有两种方式,一个是bottomNavigationBar一个是BottomAppBar。因为bottomNavigationBar会保留底部可以点击的区域,在凸起的样式中显得比较奇怪,所以使用第二种实现方式。如果只是普通的导航栏直接使用第一种最简单,大致思路就是利用Row组件结合Expanded(主要是扩展可点击区域),shape设置为凹槽结合floatingActionButton设置在中间位置

效果图

less 复制代码
import 'package:flutter/material.dart';
import './widget/business_page.dart';//简单的StatelessWidget,只包含一个text
import './widget/home_page.dart';

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

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

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  int currentIndex = 0;
  final pages = const [HomePage(), BusinessPage(), BusinessPage()];

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(primaryColor: Colors.blue),
      home: Scaffold(
        appBar: AppBar(title: const Text('Flutter demo')),
        body: pages[currentIndex],
        bottomNavigationBar: BottomAppBar(
          shape: const CircularNotchedRectangle(),//凹槽
          notchMargin: 5.0,
          padding: const EdgeInsets.fromLTRB(0, 6, 0, 6),
          child: Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            children: [
              Expanded(
                  flex: 1,
                  child: InkWell(
                    onTap: () {
                      changeCurrentIndex(0);
                    },
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Icon(Icons.home, color: getColor(0)),
                        Text('Home', style: TextStyle(color: getColor(0))),
                      ],
                    ),
                  )),
              const SizedBox(width: 80),
              Expanded(
                  flex: 1,
                  child: InkWell(
                    onTap: () {
                      changeCurrentIndex(1);
                    },
                    child: Column(
                      mainAxisSize: MainAxisSize.min,
                      children: [
                        Icon(Icons.business, color: getColor(1)),
                        Text('Business', style: TextStyle(color: getColor(1)))
                      ],
                    ),
                  ))
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          elevation: 10,
          onPressed: () {},
          child: const Icon(Icons.add, size: 36),
        ),
        floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,//位置底下中间
      ),
    );
  }

  Color getColor(int value) {
    return currentIndex == value ? Theme.of(context).primaryColor : const Color(0XFFBBBBBB);
  }

  void changeCurrentIndex(int index) {
    setState(() {
      currentIndex = index;
    });
  }
}
相关推荐
罗技12315 小时前
Easysearch 集群监控实战(下):线程池、索引、查询、段合并性能指标详解
前端·javascript·算法
XiaoYu200216 小时前
第3章 Nest.js拦截器
前端·ai编程·nestjs
千寻girling16 小时前
面试官 : “ 说一下 Map 和 WeakMap 的区别 ? ”
前端·javascript·面试
2501_9240641116 小时前
2025年主流Web自动化测试工具功能与适用场景对比
前端·测试工具·自动化
IT_陈寒16 小时前
Vite 5 实战:7个鲜为人知的配置技巧让构建速度提升200%
前端·人工智能·后端
gg1593572846016 小时前
JavaScript 核心基础
前端·javascript·vue.js
Stanford_110616 小时前
【2026新年启程】学习之路,探索之路,技术之路,成长之路……都与你同行!!!
前端·c++·学习·微信小程序·排序算法·微信开放平台
打小就很皮...16 小时前
网页包装为桌面应用(Nativefier版)
前端·桌面应用·nativefier
自由生长202417 小时前
为什么我们需要流式系统?
前端
北辰alk17 小时前
从零设计一个Vue路由系统:揭秘SPA导航的核心原理
前端·vue.js