Flutter ListView 列表控件
ListView是最常用的可滚动组件之一,它可以沿一个方向线性排布所有子组件,并且它也支持基于Sliver的延迟构建模型。Flutter中的ListView与Android中的ListView具有同等功能。
Sliver的延迟构建模型
请参见本系列文章《Flutter SingleChildScrollView 滚动控件》中的基本概念
处。
本文示例效果图(全)
1、默认构造函数
我们看看ListView的默认构造函数定义:
ListView({
...
//可滚动widget公共参数
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
EdgeInsetsGeometry padding,
//ListView各个构造函数的共同参数
double itemExtent,
bool shrinkWrap = false,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
double cacheExtent,
//子widget列表
List<Widget> children = const <Widget>[],
})
上面参数分为两组:第一组是可滚动组件的公共参数,本章第一节中已经介绍过,不再赘述;第二组是ListView各个构造函数(ListView有多个构造函数)的共同参数,我们重点来看看这些参数。
ListView通用属性值 |
含义 |
---|---|
itemExtent |
每个子控件的高度。指定itemExtent的值比不指定(自适应高度)会更高效。 |
shrinkWrap |
是否根据子组件的总高度来设置ListView的高度,默认为false 。当ListView在一个无边界(滚动方向上)的容器中时,shrinkWrap必须为true。 |
addAutomaticKeepAlives |
是否将列表项(子控件)包裹在AutomaticKeepAlive组件中,包含之后列表项滑出视口时它也不会被GC。如果列表项自己维护其KeepAlive状态,那么此参数必须置为false。 |
addRepaintBoundaries |
是否将列表项(子控件)包裹在RepaintBoundary组件中,包含之后可以避免列表项重绘。如果列表项自己维护其KeepAlive状态,那么此参数必须置为false。 |
cacheExtent |
预加载的区域。 |
不支持Sliver懒加载模型。
默认构造函数有一个children
参数,它接受一个Widget列表。这种方式适合只有少量的子组件的情况,因为这种方式需要将所有children
都提前创建好(这需要做大量工作),而不是等到子widget真正显示的时候再创建,也就是说通过默认构造函数构建的ListView没有应用基于Sliver的懒加载模型。实际上通过此方式创建的ListView
和使用SingleChildScrollView
+Column
的方式没有本质的区别。
下面是一个例子:
ListView(
padding: EdgeInsets.all(20),
children: <Widget>[
new Text("one"),
new Text("two"),
new Text("three"),
new Text("four"),
new Text("five"),
new Text("six"),
],
),
2、ListView.builder
支持Sliver懒加载模型。
ListView.builder
适合列表项比较多(或者无限)的情况,因为只有当子组件真正显示的时候才会被创建,也就说通过该构造函数创建的ListView
是支持基于Sliver的懒加载模型的。
下面看一下ListView.builder
的核心参数列表:
ListView.builder({
// ListView公共参数已省略
...
@required IndexedWidgetBuilder itemBuilder,
int itemCount,
...
})
ListView.builder属性值 |
含义 |
---|---|
itemBuilder |
它是列表项的构建器,类型为IndexedWidgetBuilder,返回值为一个widget。当列表滚动到具体的index位置时,会调用该构建器构建列表项。 |
itemCount |
列表项的数量,如果为null,则为无限列表。 |
可滚动组件的构造函数如果需要一个列表项Builder
,那么通过该构造函数构建的可滚动组件通常就是支持基于Sliver的懒加载模型
的,反之则不支持,其他可滚动组件亦是如此。
下面看一个例子:
ListView.builder(
itemCount: 100,
itemExtent: 50.0, //强制高度为50.0,可提升效率
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text("$index"));
}
);
3、ListView.separated
支持Sliver懒加载模型。
ListView.separated
可以在生成的列表项之间添加一个分割组件,它比ListView.builder
多了一个separatorBuilder
参数,该参数是一个分割组件生成器,可生成分割线。
下面我们看一个例子:奇数行添加一条蓝色下划线,偶数行添加一条绿色下划线。
class ListView3 extends StatelessWidget {
@override
Widget build(BuildContext context) {
//下划线widget预定义以供复用。
Widget divider1=Divider(color: Colors.blue,);
Widget divider2=Divider(color: Colors.green);
return ListView.separated(
itemCount: 100,
//列表项构造器
itemBuilder: (BuildContext context, int index) {
return ListTile(title: Text("$index"));
},
//分割器构造器
separatorBuilder: (BuildContext context, int index) {
return index%2==0?divider1:divider2;
},
);
}
}
4、ListView.custom
支持Sliver懒加载模型。
ListView.custom
可以自定义ListView的Item,对于复杂ListView(比如不同index对应不同布局时)需要用到它。ListView.builder
和ListView.separated
是ListView.custom
的简化版。因为 ListView 内部是靠这个 childrenDelegate 属性动态初始化子元素的。
构造方法:
ListView.builder({
// ListView公共参数已省略
...
@required this.childrenDelegate,
...
})
- childrenDelegate:
为ListView提供子委托,类型为SliverChildDelegate
。可传入SliverChildDelegate的子类SliverChildBuilderDelegate
实例。该实例可以获取到ListView的index,并根据index返回对应的Widget。适用于高度自定义ListView的情况下使用。
举个例子:
String datas =
"ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ";
Expanded(
child: ListView.custom(
itemExtent: 40.0,
childrenDelegate: SliverChildBuilderDelegate(
(BuildContext context, int i) {
Widget result;
if (i < 5) {
result = new Text(
"cus${datas.split("")[i]}",
style: new TextStyle(fontSize: 18.0, color: Colors.green),
);
} else if (i < 10) {
result = new Text(
"cus${datas.split("")[i]}",
style: new TextStyle(fontSize: 18.0, color: Colors.red),
);
} else {
result = new Text(
"cus${datas.split("")[i]}",
style: new TextStyle(fontSize: 18.0, color: Colors.blue),
);
}
return result;
},
childCount: datas.length,
),
cacheExtent: 0.0,
)),
效果图见文章开篇处。
- PHP-循环
- 日志分析实战之清洗日志小实例3:如何在spark shell中导入自定义包
- PHP-函数
- hdu----(5045)Contest(数位dp)
- hdu----(5053)the Sum of Cube(签到题,水体)
- RHEL构建DNS服务器-多区域
- hdu----(5050)Divided Land(二进制求最大公约数)
- 日志分析实战之清洗日志小实例1:使用spark&Scala分析Apache日志
- RHEL构建DNS服务器-单区域
- hdu----(5047)Sawtooth(大数相乘+数学推导)
- hdu----(4522)湫湫系列故事——过年回家(最短路)
- hdu---(1421)搬寝室(dp)
- hdu----(1257)最少拦截系统(dp/LIS)
- nginx安装Fancy美化索引目录
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法