前言

把超出屏幕显示范围会自动折行的布局称为流式布局。Flutter中通过Wrap和Flow来支持流式布局,将Row换成Wrap后溢出部分则会自动折行。

Wrap

接口描述

Wrap({
Key key,
this.direction = Axis.horizontal,
this.alignment = WrapAlignment.start,
// 主轴方向子widget的间距
this.spacing = 0.0,
// 纵轴方向的对齐方式
this.runAlignment = WrapAlignment.start,
// 纵轴方向的间距
this.runSpacing = 0.0,
this.crossAxisAlignment = WrapCrossAlignment.start,
this.textDirection,
this.verticalDirection = VerticalDirection.down,
List<Widget> children = const <Widget>[],
})

代码示例

class WrapTest extends StatelessWidget {

  @override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('流式布局-Wrap'),
),
body: Container(
child: Wrap(
// 主轴(水平)方向间距
spacing: 8.0,
// 纵轴(垂直)方向间距
runSpacing: 4.0,
// 沿主轴方向居中
alignment: WrapAlignment.center,
children: <Widget>[
Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue, child: Text('A'),),
label: Text('HelloWorld'),
), Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue, child: Text('B'),),
label: Text('WorldHello'),
), Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue, child: Text('T'),),
label: Text('FlowWorld'),
), Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue, child: Text('J'),),
label: Text('WarpHello'),
), Chip(
avatar: CircleAvatar(backgroundColor: Colors.blue, child: Text('F'),),
label: Text('Yes i do'),
), ],
),
),
);
}
}

FLow

一般很少会使用Flow,因为其过于复杂,需要自己实现子widget的位置转换,在很多场景下首先要考虑的是Wrap是否满足需求。Flow主要用于一些需要自定义布局策略或性能要求较高(如动画中)的场景。

Flow有如下优点

  1. 性能好;Flow是一个对子组件尺寸以及位置调整非常高效的控件,Flow用转换矩阵在对子组件进行位置调整的时候进行了优化:在Flow定位过后,如果子组件的尺寸或者位置发生了变化,在FlowDelegate中的paintChildren()方法中调用context.paintChild 进行重绘,而context.paintChild在重绘时使用了转换矩阵,并没有实际调整组件位置。
  2. 灵活;由于我们需要自己实现FlowDelegate的paintChildren()方法,所以我们需要自己计算每一个组件的位置,因此,可以自定义布局策略。

缺点

  1. 使用复杂。
  2. 不能自适应子组件大小,必须通过指定父容器大小或实现TestFlowDelegate的getSize返回固定大小。

接口描述

 Flow({
Key key,
@required this.delegate,
List<Widget> children = const <Widget>[],
})

代码示例

class FlowTest extends StatelessWidget {

  @override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('流式布局-Flow'),
),
body: Container(
child: Flow(
delegate: FlowDelegateTest(margin: EdgeInsets.all(10.0)),
children: <Widget>[
Container(width: 80.0, height: 80.0, color: Colors.red,),
Container(width: 80.0, height: 80.0, color: Colors.green,),
Container(width: 80.0, height: 80.0, color: Colors.blue,),
Container(width: 80.0, height: 80.0, color: Colors.yellow,),
Container(width: 80.0, height: 80.0, color: Colors.brown,),
Container(width: 80.0, height: 80.0, color: Colors.purple,),
], ),
),
); }
} class FlowDelegateTest extends FlowDelegate {
EdgeInsets margin = EdgeInsets.zero;
FlowDelegateTest({this.margin}); // Flow主要要重载这个函数,它的主要任务是确定每个子widget位置。
// 由于Flow不能自适应子widget的大小,通过在getSize返回一个固定大小来指定Flow的大小。
@override
void paintChildren(FlowPaintingContext context) {
var x = margin.left;
var y = margin.right;
// 计算每一个子widget的位置
for(int i = 0; i < context.childCount; ++i) {
var w = context.getChildSize(i).width + x + margin.right;
if (w < context.size.width) {
context.paintChild(
i,
transform: Matrix4.translationValues(x, y, 0.0)
);
x = w + margin.left;
} else {
x = margin.left;
y += context.getChildSize(i).height + margin.top + margin.bottom;
// 绘制子widget
context.paintChild(
i,
transform: Matrix4.translationValues(x, y, 0.0)
);
x += context.getChildSize(i).width + margin.left + margin.right;
}
}
} @override
Size getSize(BoxConstraints constraints) {
// 指定Flow的大小
return Size(double.infinity, 200.0);
} @override
bool shouldRepaint(FlowDelegate oldDelegate) {
return oldDelegate != this;
}
}

Flutter 布局类组件:流式布局(Wrap和Flow)的更多相关文章

  1. Flutter 布局类组件:层叠布局(Stack和Positioned)

    前言 层叠布局,即子组件可以根据距父容器四个角的位置来确定自身的位置.绝对定位运行子组件堆叠起来,即按照代码中声明的顺序. Flutter中使用Stack和Positioned这两个组件来配合实现绝对 ...

  2. Flutter 布局类组件:弹性布局(Flex)

    前言 弹性布局允许子组件按照一定比例来分配父容器空间,Flutter中的弹性布局主要通过Flex和Expanded来配合实现. Flex Flex组件可以沿着水平或垂直方向排列子组件,如果你知道主轴方 ...

  3. Flutter 布局类组件:线性布局(Row和Column)

    前言 所谓线性布局,即指沿水平或垂直方向排布子组件.Flutter中通过Row和Column来实现线性布局,并且它们都继承自弹性布局(Flex). 接口描述 Row({ Key key, // 表示子 ...

  4. 流式布局&固定宽度&响应式&rem

    我们现在在切页面布局的使用常用的单位是px,这是一个绝对单位,web app的屏幕适配有很多中做法,例如:流式布局.限死宽度,还有就是通过响应式来做,但是这些方案都不是最佳的解决方法. 1.流式布局: ...

  5. Android流式布局实现

    查看我的所有开源项目[开源实验室] 欢迎增加我的QQ群:[201055521],本博客client下载[请点击] 摘要 新项目用到了一种全新布局----Android标签流式布局的功能,正好一直说给大 ...

  6. RV LayoutManager 流式布局 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  7. 20个Flutter实例视频教程-第12节: 流式布局 模拟添加照片效果

    视频地址: https://www.bilibili.com/video/av39709290/?p=12 博客地址: https://jspang.com/post/flutterDemo.html ...

  8. Flutter 流式布局列表实例+上拉加载

    页面变化的几种方式: 一.StatefulWidget的setState形式 先声明两个变量. ; List<Map> list = []; 写了一个方法,获取数据: void _getH ...

  9. Flutter 布局类组件:简介

    前言 布局类组件都会包含一个或多个子组件,不同的布局类组件对子组件排版(layout)方式不同. 我们知道,Element树才是最终的绘制树,Element树是通过Widget树来创建的(通过Widg ...

随机推荐

  1. 把java编译成exe和安装包

    由于某些项目甲方迟迟不结算尾款,这就很烦,只能想一些办法 我们知道java,python之类的代码是没有隐私可言的,那么怎么办,总要发给甲方验收,这就要做一些操作来确保自己的利益. 通过在源代码里加上 ...

  2. Salesforce 系列(一):云服务和 Salesforce 理念简介

    本系列文章系笔者在 Salesforce 开发过程中的些许总结与心得,旨在记录自己的成长,以及为对 Salesforce 感兴趣的小伙伴提供一些帮助,如有疏漏,还望多多包涵 ~ 云服务 云服务,也称云 ...

  3. JavaSE22-Lambda表达式&方法引用

    1.Lambda表达式 1.1 Lambda表达式的标准格式 1 (形式参数) -> {代码块} 形式参数:如果有多个参数,参数之间用逗号隔开:如果没有参数,留空即可 ->:由英文中画线和 ...

  4. sonarqube代码质量检查简单使用说明

    本文翻译自sonarqube官网文档,原地址为:https://docs.sonarqube.org/latest/architecture/architecture-integration/ 一,架 ...

  5. 06-flask-文件上传案例

    前端代码 Demo.html <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  6. 精尽Spring MVC源码分析 - HandlerAdapter 组件(三)之 HandlerMethodArgumentResolver

    该系列文档是本人在学习 Spring MVC 的源码过程中总结下来的,可能对读者不太友好,请结合我的源码注释 Spring MVC 源码分析 GitHub 地址 进行阅读 Spring 版本:5.2. ...

  7. 容器编排系统k8s之Service资源

    前文我们了解了k8s上的DemonSet.Job和CronJob控制器的相关话题,回顾请参考:https://www.cnblogs.com/qiuhom-1874/p/14157306.html:今 ...

  8. python初学者-使用if条件语句判断成绩等级

    x = int(input("x=")) if x<0 or x > 100:#如果不在0--100区间内输出error print("error" ...

  9. 前端可视化开发--liveload

    在前端开发中,我们会频繁的修改html.css.js,然后刷新页面,开效果,再调整,再刷新,不知不觉会浪费掉我们很多时间.有没有什么方法,我在编辑器里面改了代码以后,只要保存,浏览器就能实时刷新.经过 ...

  10. list转long[]数组

    //list转long数组List<Long> list = new ArrayList<>(); Long[] skuIds = list.toArray(new Long[ ...