简介
ListView “滚动列表”
- 一个非常常用的控件,涉及到数据列表展示的,一般情况下都会选用该控件。
- 跟GridView相似,基本上是一个slivers里面只包含一个SliverList的CustomScrollView。
基本用法
布局行为
- ListView在主轴方向可以滚动,在交叉轴方向,则是填满ListView。
- 一个组合控件。ListView跟GridView类似,都是继承自BoxScrollView。
- 在Flutter中有几种构建ListView的方式,分别是: 默认List,ListView.builder, ListView.separated,ListView.custom。
ListView()
- 默认 List 方式,是把数据 Iterable 添加到列表中,之后直接添加到 ListView 即可。
- Tips: 如果需要设置分割线,需要对列表 item 添加处理,ListTile.divideTiles。
- 仅适用于内容较少的情形,因为它是一次性渲染所有的 items ,当 items 的数目较多时,很容易出现卡顿现象的,导致滑动不流畅。
ListView.builder()
- 设置单个item的属性,懒加载的,假如有 1000 个列表,初始渲染时并不会所有都渲染,而只会特定数量的 item ,这对于性能和用户体验来说,是很好的提升。
官方示例 ListView.separated()
- 带分割线的item,separated 相比较于 builder,又多了一个参数 separatorBuilder ,用于控制列表各个元素的间隔如何渲染。
官方示例 ListView.custom()
- 必须的参数就是 childrenDelegate , 然后传入一个 实现了 SliverChildDelegate 的组件,如 SliverChildListDelegate 和 SliverChildBuilderDelegate。
实例演示
import 'package:flutter/material.dart';
/*
* ListView 默认ListView的实例
* */
class ListViewFullDefault extends StatefulWidget {
const ListViewFullDefault() : super();
@override
State<StatefulWidget> createState() => _ListViewFullDefault();
}
/*
* ListView 默认的实例,有状态
* */
class _ListViewFullDefault extends State {
@override
Widget build(BuildContext context) {
return ListView(
);
}
}
/*
* ListView 默认的实例,无状态
* */
class ListViewLessDefault extends StatelessWidget {
final widget;
final parent;
final index;
const ListViewLessDefault([this.index, this.widget, this.parent,])
: super();
@override
Widget build(BuildContext context) {
switch(index){
case 0:
return ListView(
shrinkWrap: true,
padding: EdgeInsets.all(20.0),
children: <Widget>[
Text('I\'m dedicating every day to you'),
ListTile(
leading: Icon(Icons.map),
title: Text('Maps'),
),
Text('Domestic life was never quite my style'),
ListTile(
leading: Icon(Icons.photo_album),
title: Text('Album'),
),
Text('When you smile, you knock me out, I fall apart'),
ListTile(
leading: Icon(Icons.phone),
title: Text('Phone'),
),
Text('And I thought I was so smart'),
],
);
break;
case 1:
return SizedBox(
height: 300.0,
child: ListView.builder(
scrollDirection: Axis.vertical,
itemCount: 10, // item 的个数
itemExtent: 50.0, // 如果为非null,则强制子项在滚动方向上具有给定范围
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text("title $index"), // item 标题
leading: Icon(Icons.keyboard), // item 前置图标
subtitle: Text("subtitle $index"), // item 副标题
trailing: Icon(Icons.keyboard_arrow_right),// item 后置图标
isThreeLine:false, // item 是否三行显示
dense:true, // item 直观感受是整体大小
contentPadding: EdgeInsets.all(10.0),// item 内容内边距
enabled:true,
onTap:(){print('点击:$index');},// item onTap 点击事件
onLongPress:(){print('长按:$index');},// item onLongPress 长按事件
selected:false, // item 是否选中状态
);
},
),
);
break;
case 2:
return SizedBox(
height: 300.0,
child: ListView.separated(
scrollDirection: Axis.vertical,
itemCount: 100, // item 的个数
separatorBuilder: (BuildContext context, int index) => Divider(height:1.0,color: Colors.blue), // 添加分割线
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text("title $index"), // item 标题
leading: Icon(Icons.keyboard), // item 前置图标
subtitle: Text("subtitle $index"), // item 副标题
trailing: Icon(Icons.keyboard_arrow_right),// item 后置图标
isThreeLine:false, // item 是否三行显示
dense:true, // item 直观感受是整体大小
contentPadding: EdgeInsets.all(10.0),// item 内容内边距
enabled:true,
onTap:(){print('点击:$index');},// item onTap 点击事件
onLongPress:(){print('长按:$index');},// item onLongPress 长按事件
selected:false, // item 是否选中状态
);
},
),
);
break;
case 3:
return SizedBox(
height: 300.0,
child: ListView.custom(
scrollDirection: Axis.vertical,
childrenDelegate:SliverChildBuilderDelegate((BuildContext context, int index) {
return Container(
height: 50.0,
alignment: Alignment.center,
color: Colors.lightBlue[100 * (index % 9)],
child: Text('list item $index'),
);
}, childCount: 10),
),
);
break;
default:
return null;
break;
}
}
}