![](https://img.haomeiwen.com/i1586207/fbe7d24abb7aa4fa.png)
PS:转载请注明出处
作者: TigerChain
地址: https://www.jianshu.com/p/46808a247562
本文出自 TigerChain 简书 从头开始整 Flutter系列
教程简介
- 1、阅读对象
本篇教程适合新手阅读,老手直接略过 - 2、教程难度
初级,本人水平有限,文章内容难免会出现问题,如果有问题欢迎指出,谢谢
正文
本文主要介绍 MaterialButton 和它的孩子们 FlatButton、RaisedButton 和 OutlineButton
一、无所不在的 Button
(1)、一些 Button 举例
Button 在一个项目是必不可少的,前端好多 UI 库都把 button 专门封装成一个小组件要么是直接是 css 样式库调用即可,比如 bootstrap、ElementUi、buttons,拿 buttons「随便举个例子说一下」来说,其中的部分图片
![](https://img.haomeiwen.com/i1586207/405a0b586f1e47e5.png)
(2)、Button 的实现方式
一般情况下,做一个 Button 都是抽象成一个组件,然后给其设置对应的样式即可,比如 buttons 或是 bootstrap 的 button 都是给设置不同的 css 样式 来显示不同的效果,在 Android 中通过自定义 View 来通过属性设置显示不同的按钮样式,基本上实现方式原理都是一毛一样的
二、Flutter 中的 Buttons
在 Flutter 中一切万物皆组件, Buttons「Flutter 中并没有这个组件,这里为了说 Flutter 的 Button 组件多用了一个集合表示一下」 也不例外,也是一个组件,Flutter 中的 Buttons 基本上分为两类
1、 MaterialButton 类 Button
- FlatButton:扁平化按钮
- RaisedButton:凸起的按钮
- OutlineButton:带边框的按钮
以上三个 button 都属于 MaterialButton 的子类
2、其它 Button
- FloatingActionButton
- IconButton
- ButtonBar
- DropdownButton
- 等等其它 Button 还包括自定义的 Button 组件
我们先看 MaterialButton ,MaterialButton 搞定了,它的子类还不是菜,无非就是扩展了一下而已吗
三、MaterialButton 家族
从上面我们了解到 MaterialButton 和其子类一组成了四在家族「目前来说,保不齐后面更新了还会有更多,我们不说三方组件,只说系统支持的」,那么"擒贼先擒王",我们先看看老大 MaterialButton
(1)、MaterialButton
属性解析
不废话看构造方法
const MaterialButton({
Key key,
@required this.onPressed,
this.onHighlightChanged,
this.textTheme,
this.textColor,
this.disabledTextColor,
this.color,
this.disabledColor,
this.focusColor,
this.hoverColor,
this.highlightColor,
this.splashColor,
this.colorBrightness,
this.elevation,
this.focusElevation,
this.hoverElevation,
this.highlightElevation,
this.disabledElevation,
this.padding,
this.shape,
this.clipBehavior = Clip.none,
this.focusNode,
this.materialTapTargetSize,
this.animationDuration,
this.minWidth,
this.height,
this.child,
}) : super(key: key);
设置的属性的还是比较多的,这里挑重点解释一下
属性 | 说明 |
---|---|
onPressed | 按钮按下事事件 |
onHighlightChanged | 可以用来监听按钮的按下和放开过程 |
textTheme | 文本主题 |
textColor | 按钮文本颜色 |
disabledTextColor | 按钮禁用按钮上的文本颜色 |
color | 按钮的颜色 |
disabledColor | 按钮禁用时的颜色 |
highlightColor | 长按后按钮的颜色 |
splashColor | 点击长按水波纹的颜色 |
elevation | 阴影的范围大小 |
padding | 按钮内边距 |
shape | 按钮的形状样式 |
minWidth | 按钮最小宽度 |
height | 按钮的高度 |
child | 一般是 Text 文本组件 |
实例操练
1、color 属性
用来设置按钮颜色
显示效果
![](https://img.haomeiwen.com/i1586207/fd4402c5fbae073e.png)
核心代码
![](https://img.haomeiwen.com/i1586207/eb3250e53813b4cf.png)
PS:这里注意一点,就是如果不写 onPressed 方法或是 onPressed: 后面直接给个 null 那么给按钮设置颜色是无效的「所以说 color 也是按钮的可用时颜色,不可用颜色有 disabledColor 属性呢」
2、textColor 属性
用来设置文本颜色的属性
显示效果
![](https://img.haomeiwen.com/i1586207/682ee286b484218b.png)
核心代码
![](https://img.haomeiwen.com/i1586207/72adf6e60ed1c841.png)
同样 onPressed 方法不能为空或为 null,否则 textColor 无效
3、splashColor 属性
按钮按下的水波纹颜色设置
显示效果
![](https://img.haomeiwen.com/i1586207/2313a6be91dc01ac.gif)
核心代码
![](https://img.haomeiwen.com/i1586207/92ae38e00a350d16.png)
同样 onPressed 方法不能为空或为 null,否则 splashColor 无效「按钮都禁用了点击肯定没效果」
4、highlightColor 属性
按钮长按高亮颜色
显示效果
![](https://img.haomeiwen.com/i1586207/20d87f28d266f243.gif)
核心代码
![](https://img.haomeiwen.com/i1586207/28c798475fe9d2f8.png)
5、elevation 属性
按钮阴影大小,默认是 2 可以从源码中看到
![](https://img.haomeiwen.com/i1586207/c682779e3960a671.png)
显示效果
![](https://img.haomeiwen.com/i1586207/1ebe4cf448c7107a.png)
核心代码
![](https://img.haomeiwen.com/i1586207/f99d089d30db1773.png)
6、padding 属性
设置按钮内边距
显示效果
![](https://img.haomeiwen.com/i1586207/badab8acbbe48fd5.png)
核心代码
![](https://img.haomeiwen.com/i1586207/34e2b060cc6f1be8.png)
等屏幕宽按钮实现
我们想一下,根据我们的已有知识如何实现一个等屏幕宽的按钮呢,细心的朋友可能想到使用 Container 的 width 就可以,没错我们可以使用它实现,我们来介绍三种方式实现等屏幕宽的按钮
- (1)、使用 Container 的宽来实现
我们让 Container 的宽为等屏幕宽度即可
显示效果
![](https://img.haomeiwen.com/i1586207/baacf05c6d9f22dc.png)
核心代码
我们来封装一个组件是否根据 Container 的宽来设定按钮的宽度
![](https://img.haomeiwen.com/i1586207/147da86b74239349.png)
我们看到我们在 materialButton3 组件方法中又封装了一个组件方法 commonEqualMaterialButton 用来判断是否根据 MaterialButton 的 minWidth 来确定按钮宽度
![](https://img.haomeiwen.com/i1586207/558879bf9b3c2edb.png)
我们看如何调用
![](https://img.haomeiwen.com/i1586207/79f4379dc0271466.png)
我们可以看到通过以上调用代码会走 MaterialButton3 的 if 代码片断,那么按钮的宽度就会由 Container 的 width:double.infinity 来确定了是等屏幕宽的
- (2)、使用 MaterialButton 的 minWidth 来设置
通过上面代码的封装我们已经也看到了,当然我们还可以通过使用 MaterialButton 的 minWidth 来设置按钮的宽度
显示效果
![](https://img.haomeiwen.com/i1586207/12a46e4d0a815b9a.png)
核心代码
上面封装过了,我们直接调用即可
materialButton3('等屏幕宽2、 使用其 minwidth 实现',false),
- (3)、使用 Row 配合 Expanded 来实现
我们上节完成了等分的例子说了 Expanded 组件,如果上节中是一个子组件那么不就是等屏幕宽了么
显示效果
![](https://img.haomeiwen.com/i1586207/9faa0c3b43620a53.png)
核心代码
![](https://img.haomeiwen.com/i1586207/88bfe1456ce28f2d.png)
7、shape 属性
按钮的形状我们在开发中运用的也比较多,一般是圆角按钮和直角按钮比较常用,在 Flutter 中 shape 使用 ShapeBorder 来表示,ShapeBorder 是一个抽象类,所以我们直接看它的子类
![](https://img.haomeiwen.com/i1586207/46c83035854f1ee6.png)
我们可以看到还有和 input 相关的 Border,我们挑几个重要的说一下以下几个常用的
- roundedRectangleBorder // 矩形圆角边框
- CircleBorder // 圆形边框
- StadiumBorder // 圆角边框
- BeveledRectangleBorder// 斜角边框,可以实现直角
为了方便起见,我们封装一个共用的组件方法,只是根据设置不同的 shape 就给我显示不同的效果,如下:
![](https://img.haomeiwen.com/i1586207/dfac15f8858bd255.png)
- (1)、先看 RoundedRectangleBorder
圆角矩形,前面我们说过 Container 的 decoration 的 BoxDecoration RoundedRectangleBorder border 和 borderRadius 用法和其差不多,我们看其构造方法
const RoundedRectangleBorder({
this.side = BorderSide.none,
this.borderRadius = BorderRadius.zero,
}) : assert(side != null),
assert(borderRadius != null);
我们看到 RoundedRectangleBorder 只有两个属性边框和边框圆角,我们直接看效果吧
显示效果
![](https://img.haomeiwen.com/i1586207/8adc6627c71462eb.png)
我们来调用我们封装后的代码
![](https://img.haomeiwen.com/i1586207/603e65bda2cb6cdb.png)
封装一个 RoundedRectangleBorder 组件
![](https://img.haomeiwen.com/i1586207/0d81ff9b1e6e8f6a.png)
上面我们调用过了,这样就完成了效果图样式
- (2)、 CircleBorder
从字面意思可以知道这个 shape 是设置圆按钮的,看构造方法
const CircleBorder({
this.side = BorderSide.none })
: assert(side != null);
我们可以看到 CircleBorder 只有一个 side 属性并且不能为空「不是说我们非要传递,参数是可选的可以不传,不能为空是因为它有默认的值,它本身是不为空的」,我们来看我们做的效果吧
显示效果
![](https://img.haomeiwen.com/i1586207/d4a888222416bef1.png)
核心代码
![](https://img.haomeiwen.com/i1586207/c605c9791719ab86.png)
我们直接调用上面我们封装的方法把 CircleBorder 传递进去即可
- (3)、 StadiumBorder
StadiumBorder 半圆角矩形我们直接使用它就可以设置出来一个半圆角的按钮,看其构造方法
const StadiumBorder({
this.side = BorderSide.none})
: assert(side != null);
一样也是只有一个 side 属性,我们来看我们写的效果吧
显示效果
![](https://img.haomeiwen.com/i1586207/f07e26d18206e441.png)
核心代码
没什么好说的,继续调用我们封装的代码即可
![](https://img.haomeiwen.com/i1586207/ae514104640c2ed4.png)
在这里我们没有设置 side 有兴趣可以添加看看
- (4)、 BeveledRectangleBorder
BeveledRectangleBorder 斜角矩形,我们看看构造方法
const BeveledRectangleBorder({
this.side = BorderSide.none,
this.borderRadius = BorderRadius.zero,
}) : assert(side != null),
assert(borderRadius != null);
我们可以看到它有两个属性 side 和 borderRadius,分别设置边框和圆角大小,我们来看我们的效果
显示效果
![](https://img.haomeiwen.com/i1586207/99a8f0fda6a0bf49.png)
核心代码
![](https://img.haomeiwen.com/i1586207/4e3e8728c195fa52.png)
直接调用我们封装的代码即可,我们什么也不传就是一个直角按钮,当然实现方式有多种,比如我们可以使用上面圆角方式实现,把它的圆角设置为 0 就可以了
说了 BeveledRectangleBorder 是斜角矩形,那斜角体现在哪里呢? 我们给其设置 borderRadius 就可以实现斜角了,看显示效果
![](https://img.haomeiwen.com/i1586207/3541f09842f7da6b.png)
核心代码
![](https://img.haomeiwen.com/i1586207/423ac6479187921d.png)
好了,对于 MaterialButton 的属性我们就说这么多,我们把 MaterialButton 的几大核心属性都说了一下,那它的几个子类那就跟玩似的,大概的说一下吧「就不像 MaterialButton 这么详细的说了」
(2)、RaisedButton
RaisedButton 是凸起的按钮,怎么样的凸起呢?就是设置了一些阴影效果看起来有凸起的感觉,并且按下以后阴影会变大我们直接看效果
显示效果
![](https://img.haomeiwen.com/i1586207/d0abd64ce258366c.gif)
其实它就是是分两种状,普通状态和按下状态,并且都有阴影,看起来就有凸起的效果
核心代码
![](https://img.haomeiwen.com/i1586207/5ea9aaa73209cccd.png)
我们把 RaisedButton 做了一个简单的封装,然后我们给一个颜色看看
![](https://img.haomeiwen.com/i1586207/d9d9f6ba1ce07e35.png)
直接调用我们上面封装的组件方法给个颜色即可,效果如下:
![](https://img.haomeiwen.com/i1586207/9162260de872d9d2.gif)
这里就不多说了,玩过了 MaterialButton 它的其它属性也不在话下尝试着把玩一下即可
(3)、FlatButton
我们看 MaterialButton 第二个儿子 FlatButton,FlatButton 是扁平化按钮,默认的背景是透明「默认的 color 是 null」的也不带阴影,按下后会有背景色但是还是没有阴影,直接看效果吧
显示效果
![](https://img.haomeiwen.com/i1586207/dd63af31a3e11bab.gif)
核心代码
![](https://img.haomeiwen.com/i1586207/d01e35f377f5510c.png)
这些效果使用 MaterialButton 都可以实现,没什么好说的,这里简单的介绍一下即可
(4)、OutlineButton
我们看 MaterialButton 第三个儿子 OutlineButton,
OutlineButton 默认是带边框的按钮,且默认没有背景并且无阴影,但是按下后会出现背景并且无阴影,看效果
显示效果
![](https://img.haomeiwen.com/i1586207/4bb2181191667592.gif)
核心代码
![](https://img.haomeiwen.com/i1586207/6e3e064e640ae8e6.png)
OutlineButton 无非就是在 MaterialButton 的基础「其实是 RaisedButton」上默认重写了 shape 等属性而已,大概看一下源码,也就是在 OutlineButton 的 build 方法中,我们看一下
[图片上传失败...(image-cd3de1-1566137551597)]
![](https://img.haomeiwen.com/i1586207/972502c4328bf150.png)
PS: 这里要看的是 OutlineButton 的 build 方法非它的 icon 的 build 方法
我们可以看到 OutlineButton 返回的是一个 RaisedButton,并且默认就是重写了 shape 方法「带了边框等」并且阴影默认都是 0 「就有一个高亮时的阴影默认也是返回 0 」 ,其实学习组件就是看构造方法和 build 方法来看它有哪些特性
目前来说,我们把 MaterialButton 家族的按钮就介绍完了,只要把 MaterialButton 掌握了,其它的按钮基本上没啥好说的,我们在开发中当然可以使用 MaterialButton 来实现我们的效果,可是知道了它的孩子就可以快速来实现我们想要效果的按钮了,下面看一下其它的一些按钮
四、IconButton
IconButton 不属于 MaterialButton 家族,它继承 StatelessWidget,从字面意思就可以看出它是一个带图标的按钮「是没有文字的」,默认情况下没有背景,并且按下的时候会出现一个圆形的背景,来看构造方法
const IconButton({
Key key,
this.iconSize = 24.0,
this.padding = const EdgeInsets.all(8.0),
this.alignment = Alignment.center,
@required this.icon,
this.color,
this.focusColor,
this.hoverColor,
this.highlightColor,
this.splashColor,
this.disabledColor,
@required this.onPressed,
this.focusNode,
this.tooltip,
})
从构造方法中可以看到,IconButton 需要一个 icon 和按下事件,其它的属性 MaterialButton 中基本上都有,注意有一个 tooltip 属性「长按按钮时出一个提示语」 ,我们来看效果
显示效果
![](https://img.haomeiwen.com/i1586207/e64ce3d008329747.gif)
核心代码
![](https://img.haomeiwen.com/i1586207/81a0e44d31034f7c.png)
带 ICON 的文本按钮
我们上面说了文本按钮,也还说了 ICON 按钮,那有没有带 ICON 的文本按钮呢?答案是肯定的,其实 RaisedButton、FlatButton、OutlineButton 内置了一个带 ICON 的构造方法,我们直接使用 xxxButton.icon 就可以了,最简单的使用方法是
FlatButton.icon(
onPressed: (){},
icon: Icon(Icons.lock), // ICON
label: Text(' FlatButton.icon') // 文本
)
我们简单的显示一下:
显示效果
![](https://img.haomeiwen.com/i1586207/75d3a8516ef3ee4a.gif)
我们可以看到这些默认的效果和 RaisedButton、FlatButton、OutlineButton 默认效果是一样的,只不过多了个 icon 而已,由于我们说过 button 的 child 一般情况来说是一个文本,但是它其实是一个 widget ,本质上可以多种组合,而 flutter 内置的带 icon 的文本组件就是使用组合「child 是一个 Row 组件」来实现的,我们来看上面效果的代码
核心代码
![](https://img.haomeiwen.com/i1586207/8267ef983903214c.png)
接下来我们来看看到底 ICON 文本是如何实现的,以 FlatButton.icon 为例子来说明,我们看其构造方法,找到 _FlatButtonWithIcon 这个类,我们来具体的继承实现「我们这里不是专门的源码解析,只是大概过一下」,里面一段实现 ICON 文本的按钮的核心代码
![](https://img.haomeiwen.com/i1586207/0ebef13e58f30bfb.png)
很清楚的看到使用 Row 组件,包裹了一个 icon 和 lable 分析完毕
这节就说这么多,我们下节再介绍几个 button 比如 FloatingActionButton、ButtonBar 等,快动手敲一下吧!
作者: TigerChain 订阅查看更多内容,公号「TigerChain」同步
本文出自 TigerChain 的 从头开始整 Flutter
网友评论