06、从头开始整 Flutter--基本小部件-button(1)

本节大纲

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「随便举个例子说一下」来说,其中的部分图片

buttons 部分效果

(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 属性

用来设置按钮颜色

显示效果

显示效果

核心代码

MaterialButton color 核心代码

PS:这里注意一点,就是如果不写 onPressed 方法或是 onPressed: 后面直接给个 null 那么给按钮设置颜色是无效的「所以说 color 也是按钮的可用时颜色,不可用颜色有 disabledColor 属性呢」

2、textColor 属性

用来设置文本颜色的属性

显示效果

显示效果

核心代码

MaterialButton textColor 核心代码

同样 onPressed 方法不能为空或为 null,否则 textColor 无效

3、splashColor 属性

按钮按下的水波纹颜色设置

显示效果

显示效果

核心代码

MaterialButton splashColor 核心代码

同样 onPressed 方法不能为空或为 null,否则 splashColor 无效「按钮都禁用了点击肯定没效果」

4、highlightColor 属性

按钮长按高亮颜色

显示效果

显示效果

核心代码

MaterialButton highlightColor 核心代码

5、elevation 属性

按钮阴影大小,默认是 2 可以从源码中看到

elevation 默认值来源

显示效果

显示效果

核心代码

MaterialButton elevation 核心代码

6、padding 属性

设置按钮内边距

显示效果

显示效果

核心代码

MaterialButton padding 核心代码

等屏幕宽按钮实现

我们想一下,根据我们的已有知识如何实现一个等屏幕宽的按钮呢,细心的朋友可能想到使用 Container 的 width 就可以,没错我们可以使用它实现,我们来介绍三种方式实现等屏幕宽的按钮

  • (1)、使用 Container 的宽来实现

我们让 Container 的宽为等屏幕宽度即可

显示效果

显示效果

核心代码

我们来封装一个组件是否根据 Container 的宽来设定按钮的宽度

根据 Container 的宽度设置按钮宽度

我们看到我们在 materialButton3 组件方法中又封装了一个组件方法 commonEqualMaterialButton 用来判断是否根据 MaterialButton 的 minWidth 来确定按钮宽度

根据 MaterialButton 的 minWidth 设置按钮宽度

我们看如何调用

Container width 确定按钮宽度代码调用

我们可以看到通过以上调用代码会走 MaterialButton3 的 if 代码片断,那么按钮的宽度就会由 Container 的 width:double.infinity 来确定了是等屏幕宽的

  • (2)、使用 MaterialButton 的 minWidth 来设置

通过上面代码的封装我们已经也看到了,当然我们还可以通过使用 MaterialButton 的 minWidth 来设置按钮的宽度

显示效果

显示效果

核心代码

上面封装过了,我们直接调用即可

 materialButton3('等屏幕宽2、 使用其 minwidth 实现',false),
  • (3)、使用 Row 配合 Expanded 来实现

我们上节完成了等分的例子说了 Expanded 组件,如果上节中是一个子组件那么不就是等屏幕宽了么

显示效果

显示效果

核心代码

Row 和 Expanded 实现等屏宽按钮

7、shape 属性

按钮的形状我们在开发中运用的也比较多,一般是圆角按钮和直角按钮比较常用,在 Flutter 中 shape 使用 ShapeBorder 来表示,ShapeBorder 是一个抽象类,所以我们直接看它的子类

ShapeBorder 的子类

我们可以看到还有和 input 相关的 Border,我们挑几个重要的说一下以下几个常用的

  • roundedRectangleBorder // 矩形圆角边框
  • CircleBorder // 圆形边框
  • StadiumBorder // 圆角边框
  • BeveledRectangleBorder// 斜角边框,可以实现直角

为了方便起见,我们封装一个共用的组件方法,只是根据设置不同的 shape 就给我显示不同的效果,如下:

shape 的封装
  • (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 只有两个属性边框和边框圆角,我们直接看效果吧

显示效果

显示效果

我们来调用我们封装后的代码

RoundedRectangleBorder 调用封装

封装一个 RoundedRectangleBorder 组件

RoundedRectangleBorder 组件方法封装

上面我们调用过了,这样就完成了效果图样式

  • (2)、 CircleBorder

从字面意思可以知道这个 shape 是设置圆按钮的,看构造方法

const CircleBorder({ 
this.side = BorderSide.none }) 
: assert(side != null);

我们可以看到 CircleBorder 只有一个 side 属性并且不能为空「不是说我们非要传递,参数是可选的可以不传,不能为空是因为它有默认的值,它本身是不为空的」,我们来看我们做的效果吧

显示效果

显示效果

核心代码

CircleBorder 核心代码

我们直接调用上面我们封装的方法把 CircleBorder 传递进去即可

  • (3)、 StadiumBorder

StadiumBorder 半圆角矩形我们直接使用它就可以设置出来一个半圆角的按钮,看其构造方法

const StadiumBorder({
this.side = BorderSide.none}) 
: assert(side != null);

一样也是只有一个 side 属性,我们来看我们写的效果吧

显示效果

显示效果

核心代码

没什么好说的,继续调用我们封装的代码即可

StadiumBorder 显示效果代码

在这里我们没有设置 side 有兴趣可以添加看看

  • (4)、 BeveledRectangleBorder

BeveledRectangleBorder 斜角矩形,我们看看构造方法

const BeveledRectangleBorder({
this.side = BorderSide.none,
this.borderRadius = BorderRadius.zero,
}) : assert(side != null),
   assert(borderRadius != null);

我们可以看到它有两个属性 side 和 borderRadius,分别设置边框和圆角大小,我们来看我们的效果

显示效果

显示效果

核心代码

BeveledRectangleBorder 核心代码

直接调用我们封装的代码即可,我们什么也不传就是一个直角按钮,当然实现方式有多种,比如我们可以使用上面圆角方式实现,把它的圆角设置为 0 就可以了

说了 BeveledRectangleBorder 是斜角矩形,那斜角体现在哪里呢? 我们给其设置 borderRadius 就可以实现斜角了,看显示效果

显示效果

核心代码

BeveledRectangleBorder 斜角矩形按钮

好了,对于 MaterialButton 的属性我们就说这么多,我们把 MaterialButton 的几大核心属性都说了一下,那它的几个子类那就跟玩似的,大概的说一下吧「就不像 MaterialButton 这么详细的说了」

(2)、RaisedButton

RaisedButton 是凸起的按钮,怎么样的凸起呢?就是设置了一些阴影效果看起来有凸起的感觉,并且按下以后阴影会变大我们直接看效果

显示效果

显示效果

其实它就是是分两种状,普通状态和按下状态,并且都有阴影,看起来就有凸起的效果

核心代码

RaisedButton 默认效果代码

我们把 RaisedButton 做了一个简单的封装,然后我们给一个颜色看看

带颜色的 RaisedButton

直接调用我们上面封装的组件方法给个颜色即可,效果如下:

带颜色的 RaisedButton 效果

这里就不多说了,玩过了 MaterialButton 它的其它属性也不在话下尝试着把玩一下即可

(3)、FlatButton

我们看 MaterialButton 第二个儿子 FlatButton,FlatButton 是扁平化按钮,默认的背景是透明「默认的 color 是 null」的也不带阴影,按下后会有背景色但是还是没有阴影,直接看效果吧

显示效果

显示效果

核心代码

FlatButton 默认效果代码

这些效果使用 MaterialButton 都可以实现,没什么好说的,这里简单的介绍一下即可

(4)、OutlineButton

我们看 MaterialButton 第三个儿子 OutlineButton,
OutlineButton 默认是带边框的按钮,且默认没有背景并且无阴影,但是按下后会出现背景并且无阴影,看效果

显示效果

显示效果

核心代码

OutlineButton 效果代码

OutlineButton 无非就是在 MaterialButton 的基础「其实是 RaisedButton」上默认重写了 shape 等属性而已,大概看一下源码,也就是在 OutlineButton 的 build 方法中,我们看一下

[图片上传失败...(image-cd3de1-1566137551597)]


outline_button_source_code.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 属性「长按按钮时出一个提示语」 ,我们来看效果

显示效果

显示效果

核心代码

IconButton 效果代码

带 ICON 的文本按钮

我们上面说了文本按钮,也还说了 ICON 按钮,那有没有带 ICON 的文本按钮呢?答案是肯定的,其实 RaisedButton、FlatButton、OutlineButton 内置了一个带 ICON 的构造方法,我们直接使用 xxxButton.icon 就可以了,最简单的使用方法是

FlatButton.icon(
    onPressed: (){},
    icon: Icon(Icons.lock), // ICON
    label: Text(' FlatButton.icon') // 文本
)

我们简单的显示一下:

显示效果

显示效果

我们可以看到这些默认的效果和 RaisedButton、FlatButton、OutlineButton 默认效果是一样的,只不过多了个 icon 而已,由于我们说过 button 的 child 一般情况来说是一个文本,但是它其实是一个 widget ,本质上可以多种组合,而 flutter 内置的带 icon 的文本组件就是使用组合「child 是一个 Row 组件」来实现的,我们来看上面效果的代码

核心代码

xxxButton.icon 核心代码

接下来我们来看看到底 ICON 文本是如何实现的,以 FlatButton.icon 为例子来说明,我们看其构造方法,找到 _FlatButtonWithIcon 这个类,我们来具体的继承实现「我们这里不是专门的源码解析,只是大概过一下」,里面一段实现 ICON 文本的按钮的核心代码

FlatButton.icon 实现 icon 文本源码

很清楚的看到使用 Row 组件,包裹了一个 icon 和 lable 分析完毕

这节就说这么多,我们下节再介绍几个 button 比如 FloatingActionButton、ButtonBar 等,快动手敲一下吧!


作者: TigerChain 订阅查看更多内容,公号「TigerChain」同步
本文出自 TigerChain从头开始整 Flutter

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,271评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,275评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,151评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,550评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,553评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,559评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,924评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,580评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,826评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,578评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,661评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,363评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,940评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,926评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,156评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,872评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,391评论 2 342