Flutter学习之九 ListView

2022-11-18  本文已影响0人  MQ_Twist

极端很容易,平衡才是最难的。

👈🏻 Flutter学习之八 Container

前言

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

默认构造函数

我们看看ListView的默认构造函数定义:

ListView({
  ...  
  //可滚动widget公共参数
  Axis scrollDirection = Axis.vertical,
  bool reverse = false,
  ScrollController? controller,
  bool? primary,
  ScrollPhysics? physics,
  EdgeInsetsGeometry? padding,
  
  //ListView各个构造函数的共同参数  
  double? itemExtent,
  Widget? prototypeItem, //列表项原型,后面解释
  bool shrinkWrap = false,
  bool addAutomaticKeepAlives = true,
  bool addRepaintBoundaries = true,
  double? cacheExtent, // 预渲染区域长度
    
  //子widget列表
  List<Widget> children = const <Widget>[],
})

上面的可滑动公共参数就不再赘述了,下面是ListView各个构造函数(ListView有多个构造函数)的共同参数,我们重点来看看这些参数:

默认构造函数有一个children参数,它接受一个Widget列表(List<Widget>)。这种方式适合只有少量的子组件数量已知且比较少的情况,反之则应该使用ListView.builder 按需动态构建列表项。

注意:虽然这种方式将所有children一次性传递给 ListView,但子组件仍然是在需要时才会加载(build(如有)、布局、绘制),也就是说通过默认构造函数构建的ListView 也是基于 Sliver的列表懒加载模型。

举个栗子:

_listView() {
  return ListView(
    shrinkWrap: true,
    padding: const EdgeInsets.all(20.0),
    children: const <Widget>[
      Text('张三'),
      Text('李四'),
      Text('王五'),
      Text('赵六'),
    ],
  );
}

效果如下:


ListView.png

可以看到,虽然使用默认构造函数创建的列表也是懒加载的,但我们还是需要提前将Widget创建好,等到真正需要加载的时候才会对 Widget 进行布局和绘制。

ListView.builder

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

ListView.builder({
  // ListView公共参数已省略  
  ...
  required IndexedWidgetBuilder itemBuilder,
  int itemCount,
  ...
})

+itemBuilder:它是列表项的构建器,类型为IndexedWidgetBuilder,返回值为一个widget。当列表滚动到具体的index位置时,会调用该构建器构建列表项。

举个栗子:

_listViewBuild() {
  return ListView.builder(
      itemCount: 100,
      itemExtent: 50.0, //强制高度为50.0
      itemBuilder: (BuildContext context, int index) {
        return ListTile(title: Text("_listViewBuild $index"));
      });
}

效果如下:


ListViewBuilder.gif

ListView.separated

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

举个栗子:

_listViewSeparated() {
  // widget预定义以供复用。
  Widget blue = Container(color: Colors.blue, height: 10);
  Widget red = Container(color: Colors.red, height: 10);
  return ListView.separated(
    itemCount: 100,
    //列表项构造器
    itemBuilder: (BuildContext context, int index) {
      return ListTile(title: Text("$index"));
    },
    //分割器构造器
    separatorBuilder: (BuildContext context, int index) {
      return index % 2 == 0 ? blue : red;
    },
  );
}

效果如下:


_listViewSeparated.gif

当然还有一个场景就是,每个item之间有一定的间距,也可以用这个实现。

总结

后记

常见的列表页面ListView一般都能搞定,其对应iOS 原生的UITableView。那原生的UICollectionView呢,在Flutter中要使用GridView,这个以后再写。

上一篇下一篇

猜你喜欢

热点阅读