专栏首页阿策小和尚【Flutter 专题】61 图解基本 Button 按钮小结 (一)

【Flutter 专题】61 图解基本 Button 按钮小结 (一)

Button 在日常中是必不可少的,和尚尝试过不同类型的 Button,也根据需求自定义过,今天和尚系统的学习一下最基本的 Button

Flutter 中没有 Button Widget,但提供了很多不同类型的 Child Button Widget;和尚分析源码整体可分为 RawMaterialButtonIconButton 两类;

其中 RaisedButton / FlatButton / OutlineButton 继承自 MaterialButtonMaterialButton 是对 RawMaterialButton 的封装;而BackButton / CloseButton / PopupMenuButton 继承自 IconButton;最终 RawMaterialButtonIconButton 都是由 ConstrainedBox 填充绘制;

IconButton 系列

IconButton 系列属于图标按钮,使用相对简单;其核心是 InkResponse 水波纹效果;

IconButton

源码分析
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.highlightColor,    // 点击高亮颜色
    this.splashColor,       // 水波纹颜色
    this.disabledColor,     // 不可点击时高亮颜色
    @required this.onPressed,
    this.tooltip            // 长按提示
})

分析源码,其中 icononPressed 是必须要设置的,其余属性根据需求而适当调整;

案例尝试
  1. 和尚首先尝试最基本的 IconButton;长按会由 tooltip 提醒,点击为默认主题色;
IconButton(icon: Icon(Icons.android), tooltip: 'IconButton tootip1',
    onPressed: () => Toast.show('IconButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM));
  1. 和尚尝试其中几个属性;其中 icon 颜色为 cyan,点击高亮背景色为 deepPurple,水波纹颜色为 redAccent;注意当 icon 自身设置颜色时 color 属性不生效;
IconButton(icon: Icon(Icons.android), tooltip: 'IconButton tootip2',
    color: Colors.cyan,
    highlightColor: Colors.deepPurple.withOpacity(0.4),
    splashColor: Colors.redAccent,
    onPressed: () => Toast.show('IconButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM));
  1. 和尚尝试不可点击时,icon 颜色为 disabledColor 设置的 green;同样若 icon 本身设置了颜色,disabledColor 不生效;注意:onPressed: nullonPressed: ()=> null 不同,前者代表无点击事件;后者代表有点击事件,只是点击无操作;
IconButton(icon: Icon(Icons.android), disabledColor: Colors.green, onPressed: null);
  1. iconWidget 采用 Icon / Image / ImageIcon 等均可;
IconButton(icon: Image.asset('images/ic_launcher.png'), iconSize: 40.0, onPressed: null);

BackButton

BackButton 作用非常明确,一般用作返回上一个页面;

源码分析
const BackButton({ Key key, this.color })

分析源码,BackButton 继承自 IconButton,只允许设置图标颜色,图标样式 AndroidiOS 不同且不可修改;点击时会优先判断 maybePop 是否可以返回上一页;

案例尝试
BackButton();
BackButton(color: Colors.green);

CloseButton

CloseButton 一般用作导航栏关闭按钮与 BackButton 类似;

源码分析
const CloseButton({ Key key }) : super(key: key);

分析源码,CloseButton 继承自 IconButton,无需设置任何属性;点击时会优先判断 maybePop 是否可以返回上一页;

案例尝试
CloseButton();

RawMaterialButton 系列

RawMaterialButton

RawMaterialButtonMaterialButton 的基础,核心是由 MaterialInkWell 等组成;但不可用当前 ThemeButtonTheme 来计算未指定参数的默认值;

源码分析
const RawMaterialButton({
    Key key,
    @required this.onPressed,
    this.onHighlightChanged,            // 高亮变化的回调
    this.textStyle,                     // 文字属性
    this.fillColor,                     // 填充颜色
    this.highlightColor,                // 背景高亮颜色
    this.splashColor,                   // 水波纹颜色
    this.elevation = 2.0,               // 阴影
    this.highlightElevation = 8.0,      // 高亮时阴影
    this.disabledElevation = 0.0,       // 不可点击时阴影
    this.padding = EdgeInsets.zero,     // 内容周围边距
    this.constraints = const BoxConstraints(minWidth: 88.0, minHeight: 36.0),   // 默认按钮尺寸
    this.shape = const RoundedRectangleBorder(),    // 形状样式
    this.animationDuration = kThemeChangeDuration,  // 动画效果持续时长
    this.clipBehavior = Clip.none,                  // 抗锯齿剪切效果
    MaterialTapTargetSize materialTapTargetSize,    // 点击目标的最小尺寸
    this.child,
})

分析源码可知,RawMaterialButton 没有设置宽高的属性,可根据 padding 或外层依赖 Container 适当调整位置和大小;默认最小尺寸为 88px * 36px

案例尝试

和尚定义了一个基本的按钮,并监听其高亮改变时状态,与我们常见的按钮基本一致;

RawMaterialButton(
    padding: EdgeInsets.all(20.0),
    child: Row(mainAxisSize: MainAxisSize.min, children: <Widget>[
      Padding(child: Icon(Icons.android), padding: EdgeInsets.only(right: 10.0)),
      Text('RawMaterialButton', style: TextStyle(color: Colors.brown))
    ]),
    textStyle: TextStyle(color: Colors.pink, fontSize: 18.0),
    fillColor: Colors.greenAccent.withOpacity(0.4),
    highlightColor: Colors.cyan,
    splashColor: Colors.deepPurple.withOpacity(0.4),
    onPressed: () => Toast.show('RawMaterialButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM),
    onHighlightChanged: (state) => Toast.show('onHighlightChanged -> $state', context, duration: Toast.LENGTH_SHORT, gravity: Toast.CENTER))

FloatingActionButton

FloatingActionButtonRawMaterialButton 的封装,主要用于浮动在屏幕内容之上,一般是位于底部左右角或中间;一般一个页面只有一个;

源码分析
const FloatingActionButton({
    Key key,
    this.child,
    this.tooltip,                           // 长按提醒
    this.foregroundColor,                   // 按钮上子元素颜色
    this.backgroundColor,                   // 背景色
    this.heroTag = const _DefaultHeroTag(), // Hero 动画标签
    this.elevation = 6.0,                   // 阴影
    this.highlightElevation = 12.0,         // 高亮时阴影
    @required this.onPressed,
    this.mini = false,                      // 尺寸大小,分为 mini 和 default
    this.shape = const CircleBorder(),      // 样式形状
    this.clipBehavior = Clip.none,          // 抗锯齿剪切效果
    this.materialTapTargetSize,             // 点击目标的最小尺寸
    this.isExtended = false,                // 是否采用 .extended 方式
})
案例尝试
  1. 和尚尝试一个基本的 FloatingActionButton;长按会有 tooltip 提示;
floatingActionButton: FloatingActionButton(child: Icon(Icons.android), tooltip: 'FloatingActionButton ToolTip',
    onPressed: () => Toast.show('FloatingActionButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM));
  1. foregroundColor 为按钮上层子元素颜色,若子元素本身设置颜色则不生效;backgroundColor 为按钮背景色;
foregroundColor: Colors.redAccent.withOpacity(0.7),
backgroundColor: Colors.green.withOpacity(0.4),
  1. elevation 按钮默认阴影高度,即 z轴高度;highlightElevation 为点击高亮时阴影高度;
elevation: 0.0,
highlightElevation: 10.0,
  1. mini 是否展示成小尺寸模式;materialTapTargetSize 为配置目标的最小点击尺寸,padded 为默认的 48px * 48pxAndroid 推荐尺寸;shrinkWrap 为缩小到 Material 提供的最小尺寸;
mini: true,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
  1. shape 为样式尺寸;clipBehavior 为抗锯齿效果;
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(14.0))),
clipBehavior: Clip.antiAlias,
  1. heroTag 动画标签,默认的是 FloatingActionButtonAnimator.scaling;且 heroTag 默认是相同的,可以自定义为唯一标签;和尚设置上一页面与当前页面 FloatingActionButtonheroTag 相同;
floatingActionButtonAnimator: MyAnimation(),

heroTag: "aceTag",

class MyAnimation extends FloatingActionButtonAnimator {
  double _x, _y;

  @override
  Offset getOffset({Offset begin, Offset end, double progress}) {
    _x = begin.dx + (end.dx - begin.dx) * progress;
    _y = begin.dy + (end.dy - begin.dy) * progress;
    return Offset(_x * 0.5, _y * 0.9);
  }

  @override
  Animation<double> getRotationAnimation({Animation<double> parent}) {
    return Tween<double>(begin: 1.0, end: 1.0).animate(parent);
  }

  @override
  Animation<double> getScaleAnimation({Animation<double> parent}) {
    return Tween<double>(begin: 1.0, end: 1.0).animate(parent);
  }
}
  1. FloatingActionButton 提供了 .extended 方式创建代表标签样式的,非正方形的按钮样式;其余属性无差;
floatingActionButton: FloatingActionButton.extended(
    onPressed: () => Toast.show('FloatingActionButton.extended', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM),
    icon: Icon(Icons.android),
    label: Text('Android'));
  1. 针对特殊的个性化,FloatingActionButton 展示的大小可能会有所不同;和尚尝试了几种方式; a. 通过最基本的 RawMaterialButton 实现 FloatingActionButton 样式,外层添加 Container 约束大小;和尚比较推荐方式一,灵活性更高;
// 方式一
floatingActionButton: Container(
    width: 100.0, height: 100.0,
    color: Colors.greenAccent.withOpacity(0.4),
    child: RawMaterialButton(
        shape: CircleBorder(),
        elevation: 0.0,
        child: Icon(Icons.android),
        onPressed: () {}))

b. 借助 FittedBox 将按钮整体放大到 Container 约束范围内;

// 方式二
floatingActionButton: Container(
    width: 100.0, height: 100.0,
    child: FittedBox(
        child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {})))

c. SizeBoxFittedBox 约束方式不同,只是整体范围变大,其内部按钮按 Material 建议样式展示;

// 方式三
floatingActionButton: SizedBox(
    width: 100.0, height: 100.0,
    child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {}))

d. scaleFittedBox 类似,按比例缩放;

// 方式四
floatingActionButton: Transform.scale(
    scale: 1.5,
    child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {}))

Button 涉及的内容较多,扩展性很强,和尚分两节进行学习尝试;有些理解可能还不到位,有问题请多多指导!

本文分享自微信公众号 - 阿策小和尚(gh_8297e718c166),作者:阿策小和尚

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-09-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Android 实现圆角布局

    和尚我最近在处理图片的圆角,不止是四个角全是圆角,还包括单左侧/单右侧/对角线方向的圆角。因为自己太菜只能寻求网上的大神,发现一个自定义圆角布局,这样可...

    阿策小和尚
  • 【Flutter 专题】74 图解基本 DropdownButton 下拉选项框按钮

    和尚对于 Flutter 并不系统,总是遇到问题才会准备尝试,今天和尚准备学习一下下拉选择框;Android 提供了便利的 Spinner 而 Fl...

    阿策小和尚
  • 【Flutter 专题】56 自定义 BubbleWidget 气泡插件

    和尚在学习时想要用到气泡效果,为了更加灵活,和尚封装了一个简单的气泡插件,方便日常的使用;

    阿策小和尚
  • 盯着双11开喵铺里的小人许久,我也写了一个!cocos creator !

    ◇ 打开支付宝,天猫双11合伙人全面开喵铺的活动映入眼帘。点击进去后,我竟然盯着小人走路许久,琢磨着,自己也写个玩玩吧!

    白玉无冰
  • RocketMQ 源码分析 —— 高可用

    本文主要解析 Namesrv、Broker 如何实现高可用,Producer、Consumer 怎么与它们通信保证高可用。

    芋道源码
  • 移动端 局部dom实现滚动

    https://github.com/surmon-china/vue-awesome-swiper/issues/423

    念念不忘
  • 学习 Phaser.js HTML5游戏开发-DAY3

    3. 构建基本的子弹对象,fire 方法用来初始化子弹实例,update方法用来绘制子弹轨迹

    tonglei0429
  • 【前端词典】实现 Canvas 下雪背景引发的性能思考

    代码已上传至 github 【https://github.com/wanqihua/koa-canvas】

    小生方勤
  • es6中class类的全方面理解(二)------继承

    继承是面向对象中一个比较核心的概念。ES6 class的继承与java的继承大同小异,如果学过java的小伙伴应该很容易理解,都是通过extends关键字继承。...

    用户1272076
  • Druid学习笔记(二) - 数据连接的获取

    我们在分析mybatis执行sql的时候,最终定位到数据库连接池上。当时分析到mybatis通过数据库连接池获取到链接,然后通过连接执行sql。

    程序员_备忘录

扫码关注云+社区

领取腾讯云代金券