【Flutter 专题】98 易忽略的【小而巧】的技术点汇总 (六)
和尚继续补充日常学习中遇到的很实用的技术点;
LayoutBuilder
和尚在一些场景下需要根据父类布局大小不同展示不同的子类 Widget,例如和尚在适配大尺寸平板或横竖屏切换等场景时,此时需要用到 LayoutBuilder 和尚理解为尺寸布局构造器;
源码分析
简单分析源码可得,LayoutBuilder 是一个继承自 ConstrainedLayoutBuilder 的构造器;通过 builder 获取一个 BoxConstraints 对象,之后通过检查 constraints 来确定要展示的内容;
class LayoutBuilder extends ConstrainedLayoutBuilder<BoxConstraints> { const LayoutBuilder({ Key key, LayoutWidgetBuilder builder, }) : super(key: key, builder: builder); }
案例尝试
和尚通过 GridView 默认展示一行的图标,预期是在大部分设备上展示 4个 item,随着屏幕的变大尽可能多的展示 item,当屏幕允许展示所有 item 时为上限;于是和尚设定了单个 item 宽基础为 90,根据 size.maxWidth 进行判断;
LayoutBuilder(builder: (context, size) { if (size.maxWidth ~/ 90 >= 4 && size.maxWidth ~/ 90 <= _dataList.length) { _length = size.maxWidth ~/ 90; } else if (size.maxWidth ~/ 90 > _dataList.length) { _length = _dataList.length; } else { _length = 4; } return _gridWid(); } _gridWid() { return GridView.builder( physics: ScrollPhysics(), primary: false, shrinkWrap: true, gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: _length, mainAxisSpacing: 8.0, crossAxisSpacing: 8.0, childAspectRatio: 1), itemCount: _showMore ? _dataList.length : _length, itemBuilder: (context, index) { var dataItem = _dataList[index]; if (index < _length - 1 || _showMore) { dataItem = _dataList[index]; } else { dataItem = _dataList[_dataList.length - 1]; } return GestureDetector( child: Container( color: Colors.white70, child: Column(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[ Icon(dataItem.icon), SizedBox(height: 4), Text(dataItem.text) ])), onTap: () { if (_length < _dataList.length && dataItem.text == '更多') { _showMore = !_showMore; setState(() {}); } Toast.show(dataItem.text == '更多' ? '更多' : _dataList[index].text, context, duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM); }); }); }
ReorderableListView
和尚刚尝试了 Draggable + DragTarget 实现的基本的拖拽 GridView,今天尝试一下系统提供的 ReorderableListView 拖拽列表;
源码分析
简单分析源码可得 ReorderableListView 主要实现 children 子类 item 加载与 onReorder 拖拽子 item 到新的位置时回调;
ReorderableListView({ Key key, this.header, // 列表头部标题 @required this.children, // 列表子类 item @required this.onReorder, // 拖拽到新位置时回调 this.scrollDirection = Axis.vertical, // 滑动方向,水平或竖直 this.padding, // 内边距,仅用于 children this.reverse = false, // 是否反转 })
案例尝试
1. onReorder
onReorder 是当 item 拖拽到新的位置时 ReorderCallback 回调,其中回调中返回新旧两个数组下标用于标记;
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text('ReorderableListView Page')), body: ReorderableListView( header: Container(height: 200.0, child: ACEWave(waveWidth, waveHeight, 200.0, startOffsetXList: startOffsetX, startOffsetYList: startOffsetY, durationList: duration, waveColorList: colorList)), reverse: false, children: _listWid(), onReorder: (oldIndex, newIndex) { if (newIndex == _dataList.length) --newIndex; final temp = _dataList.removeAt(oldIndex); _dataList.insert(newIndex, temp); setState(() {}); })); } _listData(index) { return Padding( key: ValueKey(_dataList[index]), padding: EdgeInsets.all(20.0), child: Row(children: <Widget>[ Icon(_dataList[index].icon, color: Colors.black38), SizedBox(width: 10.0), Expanded(child: Text(_dataList[index].text)), Icon(Icons.arrow_right, color: Colors.black38) ])); } _listWid() => <Widget>[for (int i = 0; i < _dataList.length; i++) _listData(i)];
2. scrollDirection
scrollDirection 为列表滑动方向,与普通 ListView 一致,分为 Axis.horizontal 横行和 Axis.vertical 纵向两种;
scrollDirection: Axis.horizontal,
3. header
header 为当前列表标题头部;
_headerWid(horizontal) { return horizontal ? Container() : Container(height: 200.0, child: ACEWave(waveWidth, waveHeight, 200.0, startOffsetXList: startOffsetX, startOffsetYList: startOffsetY, durationList: duration, waveColorList: colorList)); }
4. reverse
reverse 为是否反转,即初始时是否是从最后开始;
reverse: true,
5. padding
padding 为内边距,但仅针对列表 children 部分,对于头部 header 并不起效果;
padding: EdgeInsets.all(40.0),
注意事项
-
ReorderableListView 没有类似于 ListView.builder 等构造方法,需要把 List 中所有 item 一次性加载完;
-
ReorderableListView 中所有 children item 最外层必须要有唯一的 Key;
-
和尚测试过程中,当拖拽到最后一个时,因为先 remove 掉这个 item 再 insert 添加 item 时,此时 dataList 数量已经减少,newIndex 需要减一处理;
LayoutBuilder 案例尝试 + ReorderableListView 案例尝试
和尚还会继续对日常应用的小知识点进行学习和尝试;对于底层的研究还不够深入,如有错误,请多多指导!
来源:阿策小和尚
本文分享自微信公众号 - 阿策小和尚(gh_8297e718c166)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
记一次HEX和RGB互换算法的思考及应用
由于笔者最近在开发可视化平台,所以对动态编辑器这块做了一段时间的研究, 发现其中有个小模块的知识点比较有意思,所以在这里分享一下. 作为前端工程师, 我们平时在对接设计稿的时候, 是不是经常会涉及到颜色值的转换呢? 比如从HEX值转化到RGB值, 亦或者是从RGB值转换到HEX值, 这块在PhotoShop等设计软件中非常常见, 在做类似于画板, 设计类的IDE的时候也经常会用到它们的互相转换, 还有一种场景是,为了满足老板对高大上特效的要求, 我们要让动画在不同的时间显示不同的颜色,而且有过渡效果(过渡效果虽然可以通过transiton来实现),如下: 所以笔者在这里就分享一下HEX与RGB之间相互转换的原理和算法, 并且实现随机生成HEX值和随机生成RGB值的函数,最后带着大家深度理解和掌握颜色领域的应用. 1 文章摘要 HEX与16进制 HEX转RGB算法 RGB转HEX算法 应用场景 2 HEX(16进制) 十六进制(英文名称:Hexadecimal),是计算机中数据的一种表示方法。和我们平常的表示法不一样。它由0-9,A-F组成,字母不区分大小写。与10进制的对应关系是:0-...
- 下一篇
ArcGis拓扑的那些事儿(拓扑应用过程二)
上一篇呢我写了拓扑完整的建立过程,这篇我讲一下拓扑面要素的修改方法(这次使用的数据就不给大家共享啦 )。下一篇小编会讲关于线要素拓扑的具体方法与注意事项!希望大家持续关注! 这里呢,在多说一下这个拓扑中坐标聚类的作用,虽然不起眼,但是它可以解决很多数据中潜在的问题! 这个作用主要是用于整合折点。处于拓扑容差范围内的所有折点在验证过程中均可以轻微移动。 拓扑容差范围内低等级要素的折点将被捕捉到邻近的高等级要素的折点。对处于拓扑容差范围内的同级要素折点的位置将进行几何平均。 下面我给大家看一个具体例子 此处两个折点的距离在容差范围内 进行拓扑验证 验证完成之后这两个折点在容差范围内进行了聚合(平均) 好啦,这个聚类就说到这里!下面看怎么样去修复数据。 把建好的拓扑拖入ArcMAP中 添加拓扑工具条 开始编辑 查看错误 开始修改拓扑错误。 第一种错误: 必须大于拓扑容差,这个错误拓扑规则要求要素在验证过程中不折叠。此规则是拓扑的强制规则,应用于所有的线和面要素类。在违反此规则的情况下,原始几何将保持不变,修复方式就是直接右键删除。 第二种错误: 不能有空隙 ,这个错误拓扑规则要求要素在同一图...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7安装Docker,走上虚拟化容器引擎之路
- SpringBoot2全家桶,快速入门学习开发网站教程
- MySQL8.0.19开启GTID主从同步CentOS8
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8编译安装MySQL8.0.19
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作
- Springboot2将连接池hikari替换为druid,体验最强大的数据库连接池
- 设置Eclipse缩进为4个空格,增强代码规范
- SpringBoot2整合Thymeleaf,官方推荐html解决方案