Flutter实现仿闲鱼底部导航栏效果
实现原理
底部导航栏使用bottomNavigationBar
组件
底部导航栏子元素使用BottomNavigationBarItem
组件
突起按钮的实现方式是使用 floatingActionButton
组件 + floatingActionButtonLocation
居中样式(centerDocked)
简单来说就是基于底部导航栏组件的基础上再增加一个浮动的按钮,覆盖到导航栏组件上,和中间的按钮重合在一起,最后取消掉被覆盖的按钮的点击水波纹效果。
代码演示
main.dart
import 'package:flutter/material.dart';
import './pages/tabs.dart';
void main(List<String> args) {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
title: "Test",
theme: ThemeData(
primarySwatch: Colors.red,
),
home: const Tabs(),
);
}
}
pages/tabs.dart
import 'package:flutter/material.dart';
import './tabs/category.dart';
import './tabs/home.dart';
import './tabs/setting.dart';
class Tabs extends StatefulWidget {
const Tabs({super.key});
@override
State<Tabs> createState() => _TabsState();
}
class _TabsState extends State<Tabs> {
final List<Widget> _pages = const [HomePage(), Category(), Setting()];
int _selected = 0;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text("Test"),
),
//底部导航栏
bottomNavigationBar: Theme(
//阻止点击飞溅效果(需要套一个Theme组件)
data: ThemeData(
splashColor: Colors.transparent,
highlightColor: Colors.transparent,
),
child: BottomNavigationBar(
//当前选中位置
currentIndex: _selected,
iconSize: 35, //菜单大小
fixedColor: Colors.red, //选中的颜色
unselectedItemColor: Colors.grey,
selectedFontSize: 12.0,
//4个以上菜单选项需要配置为固定
type: BottomNavigationBarType.fixed,
//侦听器
onTap: (index) {
//需要setState
setState(() {
_selected = index;
});
},
items: const [
BottomNavigationBarItem(icon: Icon(Icons.home), label: "主页"),
BottomNavigationBarItem(icon: Icon(Icons.category), label: "分类"),
BottomNavigationBarItem(
icon: Icon(Icons.add),
label: "添加",
backgroundColor: Colors.red,
),
BottomNavigationBarItem(icon: Icon(Icons.message), label: "消息"),
BottomNavigationBarItem(icon: Icon(Icons.settings), label: "设置"),
],
),
),
// 仿闲鱼的凸起按钮
floatingActionButton: Container(
width: 60,
height: 60,
padding: const EdgeInsets.all(5),
transform: Matrix4.translationValues(0, 14, 0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(30),
),
child: FloatingActionButton(
// 选中了变红色,不选中是灰色
backgroundColor: _selected == 2 ? Colors.red : Colors.blue,
onPressed: () {
setState(() {
_selected = 2;
});
},
child: const Icon(Icons.add),
),
),
// 调整floatingActionButton的位置
floatingActionButtonLocation: FloatingActionButtonLocation.centerDocked,
//最简单的方法
// body: _pages[_selected],
//也可以用indexedStack
body: IndexedStack(
alignment: Alignment.center,
index: _selected,
children: _pages,
),
);
}
}
pages/tabs/home.dart
pages/tabs/category.dart
pages/tabs/add.dart
pages/tabs/setting.dart
import 'package:flutter/material.dart';
class Category extends StatefulWidget {
const Category({super.key});
@override
State<Category> createState() => _CategoryState();
}
class _CategoryState extends State<Category> {
@override
Widget build(BuildContext context) {
return const Center(
child: Text("xx"),
);
}
}