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;
    });
  }
}
相关推荐
迷雾漫步者2 小时前
Flutter组件————FloatingActionButton
前端·flutter·dart
向前看-2 小时前
验证码机制
前端·后端
燃先生._.3 小时前
Day-03 Vue(生命周期、生命周期钩子八个函数、工程化开发和脚手架、组件化开发、根组件、局部注册和全局注册的步骤)
前端·javascript·vue.js
高山我梦口香糖4 小时前
[react]searchParams转普通对象
开发语言·前端·javascript
m0_748235244 小时前
前端实现获取后端返回的文件流并下载
前端·状态模式
m0_748240255 小时前
前端如何检测用户登录状态是否过期
前端
black^sugar5 小时前
纯前端实现更新检测
开发语言·前端·javascript
寻找沙漠的人6 小时前
前端知识补充—CSS
前端·css
GISer_Jing6 小时前
2025前端面试热门题目——计算机网络篇
前端·计算机网络·面试