Material 组件库中提供了多种按钮组件,比如 RaisedButton、FlatButton、OutlineButton、DropdownButton、RawMaterialButton、PopupMenuButton、IconButton、BackButton、CloseButton、ButtonBar、ToggleButtons等。它们都是直接或间接对RawMaterialButton组件的包装定制,所以他们大多数属性都和RawMaterialButton一样。在介绍各个按钮时我们先介绍其默认外观,而按钮的外观大都可以通过属性来自定义,我们在后面统一介绍这些属性。

另外,所有Material 库中的按钮都有如下相同点:

  1. 按下时都会有“水波动画”(又称“涟漪动画”,就是点击时按钮上会出现水波荡漾的动画)。
  2. 有一个onPressed属性来设置点击回调,当按钮按下时会执行该回调,如果不提供该回调则按钮会处于禁用状态,禁用状态不响应用户点击。

按钮常用API

按钮外观可以通过其属性来定义,不同按钮属性大同小异,我们以 RaisedButton 为例,介绍一下常见的按钮属性,详细的信息可以查看API文档。

  1. RaisedButton({
  2. Key key,
  3. //点击回调,传null 表示按钮禁用,会显示禁用相关样式
  4. @required VoidCallback onPressed,
  5. //长按回调
  6. VoidCallback onLongPress,
  7. //按钮高亮变化回调,当点击或者按住按钮时,按钮出现水波纹效果,水波纹变化时就是高亮状态。
  8. ValueChanged<bool> onHighlightChanged,
  9. MouseCursor mouseCursor,
  10. ButtonTextTheme textTheme, //ButtonTextTheme.primary, //前景色 normal accent primary
  11. Color textColor, //文本颜色
  12. Color disabledTextColor, //禁用时文字颜色
  13. Color color, //背景色
  14. Color disabledColor, //禁用时背景色
  15. Color focusColor, //聚焦时背景色
  16. Color hoverColor, //hover时背景色
  17. Color highlightColor, //高亮时背景色,即按钮按下时的背景颜色
  18. Color splashColor, //水波纹颜色,按下时会有水波纹效果
  19. Brightness colorBrightness, //按钮主题,默认是浅色主题 dark light
  20. double elevation, //阴影的范围,值越大阴影范围越大
  21. double focusElevation,
  22. double hoverElevation,
  23. double highlightElevation, //高亮阴影
  24. double disabledElevation, //禁用状态阴影
  25. EdgeInsetsGeometry padding, //内边距
  26. VisualDensity visualDensity, //视觉偏移 范围[-4.0, 4.0]
  27. ShapeBorder shape, //设置按钮的形状
  28. Clip clipBehavior = Clip.none,
  29. FocusNode focusNode,
  30. bool autofocus = false,
  31. MaterialTapTargetSize materialTapTargetSize, //默认边距padded 去掉默认边距shrinkWrap
  32. Duration animationDuration,
  33. Widget child,
  34. })

示例:定义一个背景蓝色,圆角按钮,点击时蓝色加重

image.png

  1. FlatButton(
  2. color: Colors.blue,
  3. highlightColor: Colors.blue[700],
  4. colorBrightness: Brightness.dark,
  5. splashColor: Colors.grey,
  6. child: Text("Submit"),
  7. shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(20.0)),
  8. onPressed: () {},
  9. )

主要通过shape来指定其外形为一个圆角矩形。因为按钮背景是蓝色(深色),我们需要指定按钮主题colorBrightnessBrightness.dark,这是为了保证按钮文字颜色为浅色。

Flutter 中没有提供去除背景的设置,假若我们需要去除背景,则可以通过将背景颜色设置为全透明来实现。对应上面的代码,便是将 color: Colors.blue 替换为 color: Color(0x000000)

我们也可以为这个按钮加上阴影,让它显得有质感。只需要将上面的FlatButton换成RaisedButton就行,其它代码不用改,换了之后的效果:
image.png

常规按钮

RaisedButton 凸起按钮

https://api.flutter.dev/flutter/material/RaisedButton-class.html
即”漂浮”按钮,它默认带有阴影和灰色背景。按下后,阴影会变大。
按钮 - 图3

  1. Column(
  2. children: [
  3. RaisedButton(
  4. child: Text('按钮'),
  5. onPressed: (){},
  6. ),
  7. // 有宽高的按钮
  8. Container(
  9. width: 200.0,
  10. height: 60.0,
  11. child: RaisedButton(
  12. child: Text('按钮'),
  13. onPressed: (){},
  14. ),
  15. ),
  16. ],
  17. );

image.png

FlatButton 扁平按钮

https://api.flutter.dev/flutter/material/FlatButton-class.html
扁平按钮,默认背景透明并不带阴影。按下后,会有背景色。
按钮 - 图5

  1. FlatButton(
  2. child: Text('按钮'),
  3. onPressed: () {},
  4. ),

OutlineButton 幽灵按钮

默认有一个边框,不带阴影且背景透明。按下后,边框颜色会变亮、同时出现背景和阴影(较弱)。
按钮 - 图6

  1. OutlineButton(
  2. child: Text('按钮'),
  3. onPressed: () {},
  4. ),

IconButton 图标按钮

https://api.flutter.dev/flutter/material/IconButton-class.html
是一个可点击的Icon,不包括文字,默认没有背景,点击后会出现背景。
按钮 - 图7

  1. IconButton(
  2. icon: Icon(Icons.access_alarm),
  3. onPressed: () {},
  4. iconSize: 24.0, //图标大小
  5. tooltip: '提示文案',
  6. ),

带图标的文字按钮

RaisedButtonFlatButtonOutlineButton都有一个icon 构造函数,通过它可以轻松创建带图标的按钮。
按钮 - 图8

  1. RaisedButton.icon(
  2. icon: Icon(Icons.send),
  3. label: Text("发送"),
  4. onPressed: () {},
  5. ),
  6. OutlineButton.icon(
  7. icon: Icon(Icons.add),
  8. label: Text("添加"),
  9. onPressed: () {},
  10. ),
  11. FlatButton.icon(
  12. icon: Icon(Icons.info),
  13. label: Text("详情"),
  14. onPressed: () {},
  15. ),

FloatingActionButton

https://api.flutter.dev/flutter/material/FloatingActionButton-class.html
一个圆形图标按钮,它悬停在内容之上,以展示应用程序中的主要动作。FloatingActionButton通常用于Scaffold.floatingActionButton字段。

image.png

  1. Scaffold(
  2. appBar: AppBar(title: Text('我是导航标题')),
  3. floatingActionButton: FloatingActionButton(
  4. child: Icon(Icons.add, size: 34),
  5. onPressed: () {},
  6. backgroundColor: Colors.yellow,
  7. foregroundColor: Colors.black,
  8. ),
  9. floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat, //悬浮位置
  10. );

按钮内通过Builder组件 获取按钮位置的context

  1. GlobalKey _formKey = GlobalKey();
  2. Form(
  3. key: _formKey, //设置globalKey,用于后面获取FromState
  4. child: RaisedButton(
  5. child: Text('登录'),
  6. onPressed: () {
  7. //这里获取的context是根context,不能通过这个context获取FormState
  8. print(Form.of(context)); //null
  9. // 通过_formKey.currentState 获取FormState后,
  10. // 调用validate()方法校验用户名密码是否合法,校验通过后再提交数据。
  11. if ((_formKey.currentState as FormState).validate()) {
  12. //验证通过提交数据
  13. }
  14. },
  15. ),
  16. )
  1. Form(
  2. key: _formKey,
  3. // 通过Builder来获取按钮位置所在widget树的真正context(Element)
  4. child: Builder(
  5. builder: (context){
  6. return RaisedButton(
  7. child: Text('登录'),
  8. onPressed: () {
  9. //由于本widget也是Form的子代widget,所以可以通过下面方式获取FormState
  10. if(Form.of(context).validate()){
  11. //验证通过提交数据
  12. }
  13. },
  14. );
  15. },
  16. ),
  17. )

ButtonBar 按钮组

https://api.flutter.dev/flutter/material/ButtonBar-class.html

  1. ButtonBar({
  2. Key key,
  3. this.alignment, //对齐方式 alignment: MainAxisAlignment.start,
  4. this.mainAxisSize, //min max
  5. this.buttonTextTheme, //主题色
  6. this.buttonMinWidth, //按钮最小宽度
  7. this.buttonHeight, //按钮高度
  8. this.buttonPadding, //constrained padded
  9. this.buttonAlignedDropdown,
  10. this.layoutBehavior, //constrained padded
  11. this.overflowDirection, //down up
  12. this.overflowButtonSpacing,
  13. this.children = const <Widget>[],
  14. })

示例

image.png

  1. ButtonBar(
  2. alignment: MainAxisAlignment.start,
  3. // mainAxisSize: MainAxisSize.min, //min max
  4. buttonTextTheme: ButtonTextTheme.accent,
  5. // buttonMinWidth: 200.0,
  6. // buttonHeight: 200.0,
  7. // buttonPadding: EdgeInsets.all(20.0),
  8. // buttonAlignedDropdown: true,
  9. // layoutBehavior: ButtonBarLayoutBehavior.padded, //constrained padded
  10. // overflowDirection: VerticalDirection.up, //down up
  11. // overflowButtonSpacing: 1.0,
  12. children: [
  13. RaisedButton(child: Text('按钮1'), onPressed: () {}),
  14. RaisedButton(child: Text('按钮2'), onPressed: () {}),
  15. RaisedButton(child: Text('按钮3'), onPressed: () {}),
  16. RaisedButton(child: Text('按钮4'), onPressed: () {}),
  17. ],
  18. ),

自定义按钮

lib/coms/base/buttons/MyButton.dart
  1. import "package:flutter/material.dart";
  2. class MyButton extends StatelessWidget {
  3. final text;
  4. final onPressed;
  5. final width;
  6. final height;
  7. const MyButton({
  8. key,
  9. this.text = '',
  10. this.onPressed = null,
  11. this.width = 80.0,
  12. this.height = 30.0,
  13. }) : super(key: key);
  14. @override
  15. Widget build(BuildContext context) {
  16. return Container(
  17. width: this.width,
  18. height: this.height,
  19. child: RaisedButton(
  20. child: Text(this.text),
  21. onPressed: this.onPressed,
  22. ),
  23. );
  24. }
  25. }

使用
  1. import "package:app1/coms/base/buttons/MyButton.dart";
  2. //...
  3. MyButton(
  4. text: '按钮1',
  5. onPressed: () {},
  6. ),