目录
- Flutter中的按钮
- 不完美的地方
- 在child中处理
- 外面套一个wrapper
- MaterialStateProperty
- MaterialStatesController
- 边距问题
- EnhancedButton
Flutter中的按钮
自Flutter 1.20 新增了ButtonStyleButton 系列按钮,可以说非常好用了,默认样式比之前漂亮了许多,扩展性也增加了很多。按钮样式统一由ButtonStyle这个类提供,支持根据各种状态(MaterialState)变化的属性,也增强了桌面平台也友好性。
值 |
状态 |
hovered |
鼠标滑入 |
focused |
焦点 |
pressed |
按下 |
dragged |
拖动 |
selected |
选中 |
scrolledUnder |
与滚动内容叠加 |
disabled |
不可用 |
error |
错误 |
最常用到的就是pressed和disabled还有桌面端的hovered。
可变化的属性
属性 |
说明 |
备注 |
backgroundColor |
背景色 |
Flutter3.3版本之前对应 primary或onPrimary |
foregroundColor |
前景色(文本颜色) |
Flutter3.3版本之前对应 primary或onPrimary |
elevation |
模拟物理深度 |
其实就是阴影浅重 |
fixedSize |
按钮尺寸 |
受最大尺寸和最小尺寸和布局影响 |
maxinumSize |
最大尺寸 |
|
minimumSize |
最小尺寸 |
|
mouseCursor |
鼠标图标 |
|
overlayColor |
高亮色 |
|
padding |
内容边距 |
|
shadowColor |
阴影颜色 |
|
shape |
按钮形状 |
由OutlinedBorder定义 |
side |
边框样式 |
|
surfaceTintColor |
Material3使用的材质颜色 |
|
textStyle |
文本样式 |
|
可以看到默认按钮样式,主要针对的是形状,颜色和交互效果(overlay splash),普通情况下也够用的。
不完美的地方
但是,要想进一步定制按钮效果,比如设计师提供的按钮,是渐变色的,那怎么办呢? 比较常见的做法是用Container自己写一个按钮出来。Container的decoration可以说非常好用了,支持单色,渐变,以及装饰图。AnimatedContainer还能对各种属性做动画展现。
但是 按钮要做的事情,不止是一个背景这么简单。比如上面提到的状态,以及点击反馈,语义化等等。要使用Container把这一整套实现出来,会非常繁琐。
在child中处理
Button的child可以是任何Widget,那么,把Container放到child里来实现定制背景怎样呢?且不说Button默认的padding之类的,Button的效果,都是在背景层实现的,child中的任何可见元素,都会覆盖在这层背景之上。简单来说,就是覆盖背景的同时会覆盖掉Button的Splash等overlay效果。
外面套一个wrapper
把Button套进Container里,在Container的decoration中做背景。这个方法首先要做的就是把Button的背景和阴影去除,那么除了在Container里做背景,还要模拟出Button的阴影。
AnimatedContainer(
duration: Duration(milliseconds:200),
width: width,
height: height,
transformAlignment: Alignment.center,
clipBehavior: clipBehavior,
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Colors.blue,Colors.red]
),
shadow: [BoxShadow(
...
)]
),
child: ElevatedButton(
//...
),
);
初步来看,这个方法还是可行的。重点就在于怎么把需要增强的属性组织起来,并且和按钮的状态结合起来了。
MaterialStateProperty
按钮的动态属性,都是基于这个状态属性处理的,它可以根据当前的属性集合,匹配到合适的属性提供回来。
MaterialStatesController
按钮状态的控制器,可以通过这个控制器来监听按钮的状态,做出对应处理
边距问题
ButtonStyle中有一个tapTargetSize属性(非动态属性),定义了点击目标的扩展边距,在移动设备上默认情况下按钮会向上/下多出一点边距,导致Container的背景比按钮尺寸多出一块,按钮的overlay效果铺不满,手动指定TapTargetSize.shrinkWrap就可以了。
EnhancedButton
结合以上想法,整理了style及wrapper实现了一个增加的按钮,效果如下

本来命名的ExtendedButton,结果被一个不维护的包占用了名字,就改成了EnhancedButton。虽然目前还有些许不完美的方面,以后再慢慢优化吧。
github: github.com/shirne/exte…
pub: pub.flutter-io.cn/packages/en…