Flutter 61: 图解基本 Button 按钮小结 (一)
Button 在日常中是必不可少的,小菜尝试过不同类型的 Button,也根据需求自定义过,今天小菜系统的学习一下最基本的 Button;
Flutter 中没有 Button Widget,但提供了很多不同类型的 Child Button Widget;小菜分析源码整体可分为 RawMaterialButton 和 IconButton 两类;
其中 RaisedButton / FlatButton / OutlineButton 继承自 MaterialButton 且 MaterialButton 是对 RawMaterialButton 的封装;而BackButton / CloseButton / PopupMenuButton 继承自 IconButton;最终 RawMaterialButton 和 IconButton 都是由 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 // 长按提示 })
分析源码,其中 icon 和 onPressed 是必须要设置的,其余属性根据需求而适当调整;
案例尝试
- 小菜首先尝试最基本的 IconButton;长按会由 tooltip 提醒,点击为默认主题色;
IconButton(icon: Icon(Icons.android), tooltip: 'IconButton tootip1', onPressed: () => Toast.show('IconButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM));
- 小菜尝试其中几个属性;其中 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));
- 小菜尝试不可点击时,icon 颜色为 disabledColor 设置的 green;同样若 icon 本身设置了颜色,disabledColor 不生效;注意:onPressed: null 与 onPressed: ()=> null 不同,前者代表无点击事件;后者代表有点击事件,只是点击无操作;
IconButton(icon: Icon(Icons.android), disabledColor: Colors.green, onPressed: null);
- icon 为 Widget 采用 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,只允许设置图标颜色,图标样式 Android 与 iOS 不同且不可修改;点击时会优先判断 maybePop 是否可以返回上一页;
案例尝试
BackButton(); BackButton(color: Colors.green);
CloseButton
CloseButton 一般用作导航栏关闭按钮与 BackButton 类似;
源码分析
const CloseButton({ Key key }) : super(key: key);
分析源码,CloseButton 继承自 IconButton,无需设置任何属性;点击时会优先判断 maybePop 是否可以返回上一页;
案例尝试
CloseButton();
RawMaterialButton 系列
RawMaterialButton
RawMaterialButton 是 MaterialButton 的基础,核心是由 Material 和 InkWell 等组成;但不可用当前 Theme 或 ButtonTheme 来计算未指定参数的默认值;
源码分析
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
FloatingActionButton 是 RawMaterialButton 的封装,主要用于浮动在屏幕内容之上,一般是位于底部左右角或中间;一般一个页面只有一个;
源码分析
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 方式 })
案例尝试
- 小菜尝试一个基本的 FloatingActionButton;长按会有 tooltip 提示;
floatingActionButton: FloatingActionButton(child: Icon(Icons.android), tooltip: 'FloatingActionButton ToolTip', onPressed: () => Toast.show('FloatingActionButton', context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM));
- foregroundColor 为按钮上层子元素颜色,若子元素本身设置颜色则不生效;backgroundColor 为按钮背景色;
foregroundColor: Colors.redAccent.withOpacity(0.7), backgroundColor: Colors.green.withOpacity(0.4),
- elevation 按钮默认阴影高度,即 z轴高度;highlightElevation 为点击高亮时阴影高度;
elevation: 0.0, highlightElevation: 10.0,
- mini 是否展示成小尺寸模式;materialTapTargetSize 为配置目标的最小点击尺寸,padded 为默认的 48px * 48px 为 Android 推荐尺寸;shrinkWrap 为缩小到 Material 提供的最小尺寸;
mini: true, materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
- shape 为样式尺寸;clipBehavior 为抗锯齿效果;
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(14.0))), clipBehavior: Clip.antiAlias,
- heroTag 动画标签,默认的是 FloatingActionButtonAnimator.scaling;且 heroTag 默认是相同的,可以自定义为唯一标签;小菜设置上一页面与当前页面 FloatingActionButton 的 heroTag 相同;
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); } }
- 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'));
- 针对特殊的个性化,FloatingActionButton 展示的大小可能会有所不同;小菜尝试了几种方式;
- 通过最基本的 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: () {}))
- 借助 FittedBox 将按钮整体放大到 Container 约束范围内;
// 方式二 floatingActionButton: Container( width: 100.0, height: 100.0, child: FittedBox( child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {})))
- SizeBox 与 FittedBox 约束方式不同,只是整体范围变大,其内部按钮按 Material 建议样式展示;
// 方式三 floatingActionButton: SizedBox( width: 100.0, height: 100.0, child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {}))
- scale 与 FittedBox 类似,按比例缩放;
// 方式四 floatingActionButton: Transform.scale( scale: 1.5, child: FloatingActionButton(child: Icon(Icons.android), onPressed: () {}))
Button 涉及的内容较多,扩展性很强,小菜分两节进行学习尝试;有些理解可能还不到位,有问题请多多指导!
来源: 阿策小和尚
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
谈一谈 iOS 的锁
收录:原文地址 翻看目前关于 iOS 开发锁的文章,大部分都起源于 ibireme 的《不再安全的 OSSpinLock》,我在看文章的时候有一些疑惑。这次主要想解决这些疑问: 锁是什么? 为什么要有锁? 锁的分类问题 为什么 OSSpinLock 不安全? 解决自旋锁不安全问题有几种方式 为什么换用其它的锁,可以解决 OSSpinLock 的问题? 自旋锁和互斥锁的关系是平行对立的吗? 信号量和互斥量的关系 信号量和条件变量的区别 锁是什么 锁 -- 是保证线程安全常见的同步工具。锁是一种非强制的机制,每一个线程在访问数据或者资源前,要先获取(Acquire) 锁,并在访问结束之后释放(Release)锁。如果锁已经被占用,其它试图获取锁的线程会等待,直到锁重新可用。 为什么要有锁? 前面说到了,锁是用来保护线程安全的工具。 可以试想一下,多线程编程时,没有锁的情况 -- 也就是线程不安全。 当多个线程同时对一块内存发生读和写的操作,可能出现意料之外的结果: 程序执行的顺序会被打乱,可能造成提前释放一个变量,计算结果错误等情况。 所以我们需要将线程不安全的代码 “锁” 起来。保证一段...
- 下一篇
整合到 Mockito 2
为了能够持续改进 Mockito 和在未来提升测试体验,我们希望你能够升级到 Mockito 2.10!Mockito 按照语义化版本(semantic versioning)的方式对版本进行编排,并且只在主版本升级的时候包含有重大的修改。 在库的生命周期中,有时候重大升级是必要的,通常在重大升级中包含有很多重要的新特性,对老的库进行修改甚至有可能会修改 API。 有关完整的指南和一些不兼容的修改,请参考 What's new in Mockito 2Wiki 页面中的内容。 我们希望能够享受 Mockito 2 带来的改进和便利。 Mockito Android 支持 在 Mockito version 2.6.1 中,我们原生包含 Android 支持(Android support)。 为了能够使用 Android 支持,添加 mockito-android 库到你项目的依赖中。这个 artifact 是 Mockito 项目组开发的,可以使用下面的的语法将依赖导入到你 Android 的项目中。 repositories {jcenter()}dependencies {tes...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- Red5直播服务器,属于Java语言的直播服务器
- SpringBoot2初体验,简单认识spring boot2并且搭建基础工程
- Linux系统CentOS6、CentOS7手动修改IP地址
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS8编译安装MySQL8.0.19
- CentOS7,CentOS8安装Elasticsearch6.8.6
- SpringBoot2整合Redis,开启缓存,提高访问速度
- CentOS6,CentOS7官方镜像安装Oracle11G
- Windows10,CentOS7,CentOS8安装Nodejs环境