Flutter开发 10.Widget-ListView详解

16 篇文章 0 订阅

Flutter开发 10.Widget-ListView详解

1.ListTile

ListTile 是用来做列表中的每一个项目的布局,有点像iOS的UITableViewCell或者安卓的列表用的Adapter,ListTile提供的常用参数如下:

参数类型说明
titleWidget?标题组件 (⚠️ 注意不是一个字符串)
subtitleWidget?副标题组件,在主标题下方 (⚠️ 注意不是一个字符串)
leadingWidget?左侧开头位置的组件
trailingWidget?右侧结尾位置的组件
isThreeLinebool是否显示为三行
densebool是否使用密集的布局, 主要用在屏幕较小,或要显示的内容软多的时候
visualDensitybool密集的布局程度
shapeShapeBorder?形状, 可以加边框颜色等
contentPaddingEdgeInsetsGeometry?内间距
enabledbool是否可用
onTapGestureTapCallback?点击事件回调
onLongPressGestureLongPressCallback?长按事件回调
mouseCursorMouseCursor?鼠标光标
selectedbool选中状态,默认为 false
focusColorColor?获得焦点时的颜色
hoverColorColor?悬停颜色
focusNodeFocusNode?焦点相关消息监控,可以处理一系列焦点相关的操作
autofocusbool是否自动聚焦

2.ListView

ListView是最常用的可滚动组件之一,它可以沿一个方向线性排布所有子组件,并且它也支持列表项懒加载(在需要时才会创建)。

2.1 默认构造函数

通常ListView的默认构造函数,只能通过children来指定多个Item组件,它接受一个Widget列表(List)。这种方式适合只有少量的子组件数量已知且比较少的情况,比如你只需要做3个样子不完全一样的选项的Item,只是写成静态的效果,也不需要复用布局时,可以使用这种方式。

2.2 ListView.builder

ListView.builder适合列表项(Item)比较多或者列表项数量不能确定的情况,下面看一下主要的核心参数列表:

参数类型说明
itemCountint?列表项的数量,如果为null,则为无限列表。
itemExtentdouble?如果不为null,每一个Item列表项的“长度”为itemExtent的值;这里的“长度”是指滚动方向上子组件的长度,也就是说如果滚动方向是垂直方向,则itemExtent代表Item列表项的高度;如果滚动方向为水平方向,则itemExtent就代表Item列表项的宽度。
prototypeItemWidget?我们可以指定一个列表项样本来计算高度,该列表项被称为 prototypeItem(列表项原型)。指定 prototypeItem 后,可滚动组件会在 layout 时计算一次它延主轴方向的长度,这样也就预先知道了所有列表项的延主轴方向的长度,所以和指定 itemExtent 一样,指定 prototypeItem 会有更好的性能。注意,itemExtent 和prototypeItem 互斥,不能同时指定它们。如果同时指定将得到错误:Failed assertion: line 1156 pos 10: ‘itemExtent == null || prototypeItem == null’: You can only pass itemExtent or prototypeItem, not both.
itemBuilderIndexedWidgetBuilder返回值为一个widget。当列表滚动到具体的index位置时,会调用该构建器构建列表项。index最大值为itemCount-1
shrinkWrapbool是否根据子组件的总长度来设置ListView的长度,默认值为false 。默认情况下,ListView的会在滚动方向尽可能多的占用空间。当ListView在一个无边界(滚动方向上)的容器中时,shrinkWrap必须为true。

2.3 ListView.separated

ListView.separated可以在生成的列表项之间添加一个分割组件,它比ListView.builder多了一个separatorBuilder参数,该参数是一个分割组件生成器。

参数类型说明
separatorBuilderIndexedWidgetBuilder列表项之间添加一个分割组件

3. 实例演示


class ModelItem {
  String? strTitle;
  String? strSubTitle;
  IconData? iconData;
  ModelItem(this.strTitle, this.strSubTitle, this.iconData);
}

const String kSubTitle = "abcdefghijklmnopqrstuvwxyz-1234567890";
List<ModelItem> itemDatas = <ModelItem>[
  ModelItem("zz-列表项测试数据1", kSubTitle, Icons.access_alarm),
  ModelItem("zz-列表项测试数据2", kSubTitle, Icons.backpack),
  ModelItem("zz-列表项测试数据3", kSubTitle, Icons.cabin),
  ModelItem("zz-列表项测试数据4", kSubTitle, Icons.dashboard),
  ModelItem("zz-列表项测试数据5", kSubTitle, Icons.face),
  ModelItem("zz-列表项测试数据6", kSubTitle, Icons.gamepad),
  ModelItem("zz-列表项测试数据7", kSubTitle, Icons.hail),
  ModelItem("zz-列表项测试数据8", kSubTitle, Icons.kayaking),
  ModelItem("zz-列表项测试数据9", kSubTitle, Icons.label),
  ModelItem("zz-列表项测试数据10", kSubTitle, Icons.male),
  ModelItem("zz-列表项测试数据11", kSubTitle, Icons.nat),
  ModelItem("zz-列表项测试数据12", kSubTitle, Icons.offline_share),
  ModelItem("zz-列表项测试数据13", kSubTitle, Icons.padding),
];

void main() {
  runApp(MaterialApp(
      home: Scaffold(
          appBar: AppBar(
            title: const Text("爪爪课堂"),
          ),
          body: ListView.separated(
            itemCount: itemDatas.length,
            separatorBuilder: (BuildContext context, int index) {
              return Container(color: Colors.red, height: 10);
            },
            itemBuilder: (BuildContext context, int index) {
              return Center(
                child: ListTile(
                  // contentPadding: const EdgeInsets.fromLTRB(10, 0, 10, 10),
                  shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(10),
                      side: const BorderSide(
                          color: Color.fromARGB(255, 216, 216, 216))),
                  leading: Container(
                    // color: Colors.blue,
                    width: 30,
                    alignment: Alignment.center,
                    child: Icon(
                      itemDatas[index].iconData,
                      size: 30,
                    ),
                  ),
                  title: Text(itemDatas[index].strTitle!),
                  subtitle: Text(itemDatas[index].strSubTitle!),
                  trailing: const Icon(Icons.arrow_right),
                ),
              );
            },
          ))));
}

执行后效果如下:
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xuanwenchao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值