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;
    });
  }
}
相关推荐
web行路人6 分钟前
React中类组件和函数组件的理解和区别
前端·javascript·react.js·前端框架
超雄代码狂28 分钟前
ajax关于axios库的运用小案例
前端·javascript·ajax
长弓三石36 分钟前
鸿蒙网络编程系列44-仓颉版HttpRequest上传文件示例
前端·网络·华为·harmonyos·鸿蒙
小马哥编程37 分钟前
【前端基础】CSS基础
前端·css
嚣张农民1 小时前
推荐3个实用的760°全景框架
前端·vue.js·程序员
周亚鑫1 小时前
vue3 pdf base64转成文件流打开
前端·javascript·pdf
Justinc.2 小时前
CSS3新增边框属性(五)
前端·css·css3
neter.asia2 小时前
vue中如何关闭eslint检测?
前端·javascript·vue.js
~甲壳虫2 小时前
说说webpack中常见的Plugin?解决了什么问题?
前端·webpack·node.js
嚣张农民2 小时前
JavaScript中Promise分别有哪些函数?
前端·javascript·面试