Widget for Week: Button

Flutter 中 Button 的使用也非常简单。
Flutter 中的 button 都是 MaterialButton ,这个是基类,所以常见的都是基于他衍生的,官方为我们提供了几个常用的 button,[FlatButton],[OutlineButton],[RaisedButton],下面就一一介绍,并例举一些常用的 case 的样式处理。


image.png

本文基于源码 1.10.2

  • RaisedButton :凸起的按钮,其实就是Android中的Material Design风格的Button ,继承自MaterialButton
  • FlatButton :扁平化的按钮,继承自MaterialButton
  • OutlineButton :带边框的按钮,继承自MaterialButton,其实就是设置了 shape 的 RaisedButton
  • IconButton :图标按钮,继承自StatelessWidget,其实等同于上边的 Button 设置 child 为 Icon

先来看一下 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.autofocus = false,
    this.materialTapTargetSize,
    this.animationDuration,
    this.minWidth,
    this.height,
    this.child,
  })
属性 值类型 说明
onPressed VoidCallback 必填参数,按下回调,设置为 null 则表示禁用,会启用禁用的样式
child Widget Button 上要显示的组件
textColor Color 组件的颜色,比如child 为 Text 时就是设置了 Text 的字体颜色
color Color button 的颜色
disabledColor Color 按钮禁用时候的颜色
disabledTextColor Color 按钮禁用的时候的child 颜色
splashColor Color 水波纹颜色
highlightColor Color 长按时按钮的颜色
elevation double 阴影的范围大小,值越大阴影范围越大
padding EdgeInsetsGeometry 内边距
shape ShapeBorder 设置形状
minWidth double 最小宽度
height double 高度

经过上述属性,基本上就能搭配出来你想要的任何的按钮样式了。

RaisedButton 和 FlatButton 都是直接继承 MaterialButton,所以默认使用的样式大同小异,唯一区别就是 FlatButton扁平化,没有凸起的背景色,所以比较适合给 Text 设置点击事件的。

属性介绍完毕,相信大家都有个印象,对比自己的 Android 或者 iOS 经验,也都能脑补出来样式。。。
下边就说一下开发中常用的一些样式。

padding

很多时候,按钮中间的文字,是需要给一点距离的,文字距离上下左右都有一定边距,此时就需要用到 padding 属性,如下代码就是给 Text 四周设置了 20 的边距,距离按钮边框,当然你也可以用EdgeInsets.only()给具体的某一个(几个)方向设置边距,使用EdgeInsets.symmetric()给水平或者垂直方向设置边距。

 RaisedButton(
              onPressed: () {
                _showSnackBar("RaisedButton 设置内边距20");
              },
              child: Text("RaisedButton 设置内边距20"),
              padding: const EdgeInsets.all(20),
            ),

shape

shape 的值是 ShapeBorder ,抽象类,他有几个常见的实现类

  • BeveledRectangleBorder 带斜角的长方形边框
  • CircleBorder 圆形边框
  • RoundedRectangleBorder 圆角矩形
  • StadiumBorder 两端是半圆的边框

对应的都要两个属性:slide ,borderRadius

圆角矩形
如下代码可实现圆角矩形的边框形状,当然了如果你要是想实现 iOS 样式的大圆角的按钮,只需要把 Radius 的值设置的大一点就行了。

RaisedButton(
              onPressed: () {},
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(10)),
              ),
              child: Text(
                "RaisedButton 圆角背景(小)",
                style: TextStyle(fontSize: 10),
              ),
            ),

iOS 样式 按钮
在 IOS 设备上,按钮都是两头半圆样式的,那么就可以简单的实现,两种方案:
1.给RoundedRectangleBorder 的 Radius 设置的超级大
2.直接使用 StadiumBorder()设置为 shape

RaisedButton(
              onPressed: () {},
              shape: RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(300)),
              ),
              child: Text(
                "RaisedButton 圆角背景(iOS 样式)",
                style: TextStyle(fontSize: 10),
              ),
            ),
RaisedButton(
              onPressed: () {},
              shape: StadiumBorder(),
              child: Text(
                "StadiumBorder 两头半圆",
                style: TextStyle(fontSize: 10),
              ),
            ),

圆形按钮
使用 CircleBorder 可以实现圆形的按钮样式

RaisedButton(
              onPressed: () {},
              padding: const EdgeInsets.all(20),
              shape: CircleBorder(),
              child: Text(
                "圆形样式",
                style: TextStyle(fontSize: 10),
              ),
            ),

斜角的矩形
实现带斜角的矩形,也很简单,直接使用BeveledRectangleBorder就行了,BorderRadius 的值的大小,可以帮助你实现各式各样的斜角。。。
值越大,斜的越厉害,如果设置为 0,就是标准的矩形。

RaisedButton(
              color: Colors.red,
              onPressed: () {},
              shape: BeveledRectangleBorder(
                  borderRadius: BorderRadius.circular(10)),
              child: Text(
                "StadiumBorder 两头半圆",
                style: TextStyle(fontSize: 10),
              ),
            ),

以上实现的一些样式,都是纯色的,单纯的背景色,下边再来实现一些带边框的样式,
BorderShape 的几个实现类里边,都有两个属性:slide 和 borderRadius.
slide 属性可以设置背景色,边框颜色,边框的背景等
borderRadius 就是设置弧形程度。

实现一个红色边框,宽度为 1,白色背景的边框
红色边框用 side 里边的 color 来设置,宽度用 width 设置

 RaisedButton(
              onPressed: () {},
              color: Colors.white,
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10),
                  side: BorderSide(color: Colors.red)),
              child: Text("RaisedButton"),
            ),

渐变色按钮
Flutter 中的按钮不支持实现渐变色,所以需要依靠 Container 来帮忙,只需要给按钮的 child套一个 Container,给 Container 设置渐变色就行了。但是需要考虑到处理 button 自带的默认的内边距,一定要记得去掉,不然会很难看。。。

Theme(
              child: RaisedButton(
                onPressed: () {},
                elevation: 0.0,
                color: Colors.white,
                shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(10),
                ),
                child: Container(
                  child: Text("RaisedButton"),
                  padding: EdgeInsets.fromLTRB(16, 8, 16, 8),
                  decoration: BoxDecoration(
                      borderRadius: BorderRadius.circular(10),
                      gradient:
                          LinearGradient(colors: [Colors.green, Colors.red])),
                ),
              ),
              data: ThemeData().copyWith(
                  buttonTheme:
                      ButtonThemeData(padding: const EdgeInsets.all(0))),
            ),

不知道大家有没有发现,按钮在使用过程中,有一个自己的默认的宽高,仔细看看源码,发现是在按钮的主题里边设置了,如下代码,
所以如果你想去掉这个默认值,可以在 Theme 里边进行设置,可以直接在最外层的 MaterialApp 中设置,也可以给按钮嵌套一个 Theme()进行处理。如下代码采用了第二个方案。

ButtonThemeData({
    this.textTheme = ButtonTextTheme.normal,
    this.minWidth = 88.0,
    this.height = 36.0,
    EdgeInsetsGeometry padding,
    ShapeBorder shape,
    this.layoutBehavior = ButtonBarLayoutBehavior.padded,
    this.alignedDropdown = false,
    Color buttonColor,
    Color disabledColor,
    Color focusColor,
    Color hoverColor,
    Color highlightColor,
    Color splashColor,
    this.colorScheme,
    MaterialTapTargetSize materialTapTargetSize,
  })
 Theme(
              child: RaisedButton(
                onPressed: () {},
                color: Colors.white,
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(10),
                    side: BorderSide(color: Colors.red, width: 4)),
                child: Text("去掉默认宽高"),
              ),
              data: ThemeData().copyWith(
                  buttonTheme: ButtonThemeData(minWidth: 10, height: 20)),
            ),

带图片/图标的按钮
有时候需要实现一些带有图标的按钮,那么可以用 RaisedButton ,通过 child 嵌套实现,也可以直接使用 IconButton

 RaisedButton(
              onPressed: () {},
              child: Row(
                mainAxisSize: MainAxisSize.min,
                children: <Widget>[Icon(Icons.add), Text("带图标")],
              ),
            ),
            SizedBox(width: 10),
            FlatButton(
              onPressed: () {},
              child: Icon(
                Icons.add,
                color: Colors.red,
              ),
            ),
            SizedBox(width: 10),
            IconButton(
              onPressed: () {},
              icon: Icon(
                Icons.add,
                color: Colors.red,
              ),
            ),

OK,今日份 按钮相关内容搞定,后续有遇到其他的样式,再更新进来。。。

源码链接:https://github.com/yanftch/book/blob/master/lib/demo/widgets/w_button.dart

收拾收拾,放假啦~~
预祝小伙伴们假期愉快😸😸😸

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