这是我参与更文挑战的第18天,活动详情查看: 更文挑战
上一篇我们聊了底部导航栏
BottomNavigationBar
的使用详解,这篇我们聊聊 FloatingActionButton 与 BottomAppBar的使用,为啥要放到一起呢?只有这两个 Widget 组合在一起才可以出效果,单独聊没有太大的价值,因为使用都比较简单。
比如这些奇怪的导航,我们要怎么实现?
凹凸菜单 | 圆角导航 | 波浪导航 |
---|---|---|
FloatingActionButton
实现上面的效果前,我们先聊聊
FloatingActionButton
(中间蓝色加号按钮),然后再与下面的
BottomAppBar
结合即可
先看整体结构
Scaffold(
body:[bodyWidget],
// 这里设置悬浮按钮
floatingActionButton: FloatingActionButton(
// 设置一个➕按钮
child: Icon(Icons.add),
// 添加点击事件
onPressed: () {
一般我们使用它就是在 Scaffold
中设置即可,当然他是一个 Widget 我们在任何地方都可以使用他。
backgroundColor: Colors.orange foregroundColor: Colors.orange splashColor: Colors.orange elevation: 0 elevation: 6(默认) highlightElevation: 12 mini: true shape: RoundedRectangleBorder shape: ContinuousRectangleBorder
FloatingActionButton(
child: Icon(Icons.add),
// backgroundColor: Colors.orange,
// foregroundColor: Colors.orange,
// splashColor: Colors.orange,
// elevation: 6,
// highlightElevation: 12,
// mini: true,
// shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
// shape: ContinuousRectangleBorder(
// side: BorderSide(
// width: 4,
// color: Colors.orange,
// ),
// borderRadius: BorderRadius.circular(12),
// ),
// shape: BeveledRectangleBorder(
// side: BorderSide(
// width: 4,
// color: Colors.orange,
// ),
// borderRadius: BorderRadius.circular(12),
// ),
onPressed: () {
上面是写基本的设置的属性,有时我们还有一些特殊的需求,比如
你会发现除了刚才设置的 mini 和默认大小外,没有属性可以设置大小,那么我们就在外层包一层 SizedBox
即可。
SizedBox(
width: 80,
height: 80,
child: FloatingActionButton(...),
比如我们做上下排列的效果,那么我们只需要添加一个 Column 即可,里面放置多个 FloatingActionButton 即可
Column(
mainAxisSize: MainAxisSize.min,
children: [
FloatingActionButton(
child: Icon(Icons.ac_unit_rounded),
backgroundColor: Colors.orange,
onPressed: () {},
SizedBox(height: 10),
FloatingActionButton(
child: Icon(Icons.adb_sharp),
backgroundColor: Colors.green,
onPressed: () {},
SizedBox(height: 10),
FloatingActionButton(
child: Icon(Icons.more_horiz_outlined),
onPressed: () {},
FloatingActionButton
还有个 heroTag
属性我们没有聊,这个是干嘛用的呢?这个就是 Hero
widget 的标签,如果此时我们设置点击跳转到一个新的页面,那么会报错,因为在 material
的设计规范里,每个屏幕只能有一个悬浮按钮,如果多个的话,在路由导航是就会出现标签冲突(不设置都是默认标签对象),解决版本就是设置不同的 heroTag
即可。
Column(
mainAxisSize: MainAxisSize.min,
children: [
FloatingActionButton(
child: Icon(Icons.ac_unit_rounded),
backgroundColor: Colors.orange,
// 设置 tag1
heroTag: 'tag1',
onPressed: () {},
SizedBox(height: 10),
FloatingActionButton(
child: Icon(Icons.adb_sharp),
backgroundColor: Colors.green,
// 设置 tag2
heroTag: 'tag2',
onPressed: () {},
SizedBox(height: 10),
FloatingActionButton(
child: Icon(Icons.more_horiz_outlined),
// 设置 tag3
heroTag: 'tag3',
onPressed: () {},
如上图我们可以通过 Scaffold
的 floatingActionButtonLocation
属性来设置 FloatingActionButton
的位置,为了更好的展示,我们增加一个 BottomAppBar
来帮助我们理解各个属性的调配
BottomAppBar
上一篇我们聊过 BottomNavigationBar
,这里我们将 bottomNavigationBar
属性改为 BottomAppBar
,因为 Flutter 中所有的控件都是 Widget
Scaffold(
// 设置位置,中心停靠
floatingActionButtonLocation:FloatingActionButtonLocation.centerDocked,
// 设置 BottomAppBar
bottomNavigationBar: BottomAppBar(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: [
TextButton.icon(
icon: Icon(Icons.home),
label: Text('首页'),
onPressed: () {},
SizedBox(),
TextButton.icon(
icon: Icon(Icons.people),
label: Text('我的'),
onPressed: () {},
非 mini
小表展示了各种位置效果,觉得有用记得点赞支持我哦
startFloat centerFloat endFloat startDocked centerDocked endDocked startTop centerTop endTop
mini 类型
这个需要配合 FloatingActionButton
中的 mini
属性来使用,并且位置属性加了前缀 mini
,如 FloatingActionButtonLocation.miniCenterDocked
,位置与上面是一致的。
区别在于 BottomAppBar
设置缺口 shape
的时候,缺口的半径不同
centerDocked miniCenterDocked
多形状 Shape
在 Flutter 很多 Widget 都是可以设置 Shape 来自定义形状的,从输入框的边框线条到背景都是如此。
圆形缺口矩形
BottomAppBar(
/// 圆形缺口矩形
shape: CircularNotchedRectangle(),
child: [childWidget],
BottomAppBar(
/// 自动缺口形状
shape: AutomaticNotchedShape(
// 斜角矩形
BeveledRectangleBorder(
borderRadius: BorderRadius.circular(20),
child: [childWidget],
BottomAppBar(
/// 自动缺口形状
shape: AutomaticNotchedShape(
// 圆角矩形
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(40),
child: [childWidget],
自定义形状
如果上面的一些效果也不能满足我们的需求,我们可以选择自定义 Shape,具体怎么自定义可以看下面的代码,当然如果你阅读 Flutter 的源码会更好。
BottomAppBar(
/// 自定义形状
shape: MyShape(),
child: [childWidget],
/// 自定义Shape
class MyShape extends NotchedShape {
@override
Path getOuterPath(Rect host, Rect? guest) {
var path = Path();
int wallCount = 10;
double step = host.width / wallCount;
double wall = host.height / 4;
for (var i = 0; i < wallCount; i++) {
// 上下起伏的锯齿状
path.relativeLineTo(step, i.isEven ? -wall : wall);
// 分别连接到右下角、左下角、闭合左上角
..lineTo(host.right, host.bottom)
..lineTo(host.left, host.bottom)
..close();
return path;
/// 自定义Shape
class MyShape extends NotchedShape {
@override
Path getOuterPath(Rect host, Rect? guest) {
var path = Path();
int wallCount = 10;
double step = host.width / wallCount;
double wall = host.height / 4;
for (var i = 0; i < wallCount; i++) {
// 圆角波浪
path.relativeArcToPoint(
Offset(step, i.isEven ? -wall : wall),
radius: Radius.circular(20),
// 分别连接到右下角、左下角、闭合左上角
..lineTo(host.right, host.bottom)
..lineTo(host.left, host.bottom)
..close();
return path;
基于 Flutter 🔥 最新版本
Flutter Widgets 仓库
FloatingActionButton (Flutter Widget of the Week)
Flutter-FloatingActionButton
Flutter-BottomAppBar
此文章已收录到下面👇 的专栏,可以直接关注
更多文章继续阅读|系列文章持续更新
👏 欢迎点赞➕收藏➕关注,有任何问题随时在下面👇评论,我会第一时间回复哦