ListView 是一个线性布局的widgets 列表.
ListView -extends->BoxScrollView -extends->ScrollView -extends->StatelessWidget
ListView是最常用的滑动组件。它在滚动方向上一个接一个地显示它的孩子。在交叉轴中,需要孩子填充ListView。
如果子控件非空,使用 itemExtent
强制指定子控件高度范围。通过itemExtent
设置值,比子控件自己决定范围更高效,因为滚动机制可以通过设置的预设的itemExtent来节约工作,比如在滚动位置急剧变化的时候。
在构建ListView时有4中选择:
- 利用显示的自列表来构造
List<Widget>
。此构造函数适合于具有少量子元素的列表视图,因为构造列表需要为可能显示在列表视图中的每个子元素执行工作,而不仅仅是那些实际可见的子元素。 -
ListView.builder
利用IndexedWidgetBuilder
来按需构造。这个构造函数适合于具有大量(或无限)子视图的列表视图,因为构建器只对那些实际可见的子视图调用。 - 使用
ListView.separated
构造函数,采用两个IndexedWidgetBuilder:itemBuilder
根据需要构建子项separatorBuilder
类似地构建出现在子项之间的分隔符子项。此构造函数适用于具有固定数量的子控件的列表视图。 - 使用
ListView.custom
的SliverChildDelegate
构造,它提供了定制子模型的其他方面的能力。 例如,SliverChildDelegate
可以控制用于估计实际上不可见的孩子的大小的算法。
控制滚动的初始offset,可以通过设置ScrollController.initialScrollOffset
属性。
默认情况下,ListView将自动填充列表的可滚动的末端,以避免MediaQuery的填充所指示的部分阻塞。若要避免此行为,请重写可以空的padding
属性。
ListView.builder demo
body: new ListView.builder(
padding: new EdgeInsets.all(5.0),
itemExtent: 50.0,
itemBuilder: (BuildContext context,int index){
return new Text("text $index");
},
),
image.png
这里的listView 可以无限往下滑动;)
ListView.separated demo
body: new ListView.separated(
itemBuilder: (BuildContext context, int index) {
return new Text("text $index");
},
separatorBuilder: (BuildContext context, int index) {
return new Container(height: 1.0, color: Colors.red);
},
itemCount: 40),
image.png
子结点的生命周期
1.创建
在布局列表时,可见的子元素、状态和呈现对象将基于现有控件(例如当使用默认构造函数时)或延迟提供的控件(例如当使用ListView.builder构造函数时)延迟地创建。
2.销毁
当从视图滑出时,关联的元素子树、状态和呈现对象将被销毁。当向后滚动时,位于列表中相同位置的新子节点将与新元素、状态和呈现对象一起延迟地重新创建。
3.销毁时的数据保存
为了保存子元素在视图中滚动和退出视图时的状态,可以做以下选择:
1> 将与UI状态驱动无关的业务逻辑从列表子子树中移出。例如,如果一个列表包含来自高速缓存的网络响应的带有上投票数的帖子,那么将帖子列表和上投票数存储在列表外部的数据模型中。让列表子UI子树很容易从真实模型对象的源中重新创建。使用子控件子树中的StatefulWidget
只存储瞬时UI状态。
2> 让KeepAlive
作为需要保存的列表子控件子树的root结点。KeepAlive
使得孩子子树的顶部结点渲染对象的子结点保持存活。当关联的顶部渲染对象滚动到视图之外时,列表将子对象的渲染对象(以及通过扩展,其关联的元素和状态)保存在高速缓存列表中,而不是销毁它们。当滚动回到视图中时,渲染对象将按照当前现状被重新绘制(如果在中间阶段没有被标记为脏)。
这只在addAutomaticKeepAlives
和addRepaintBoundaries
为false的情况下有效,因为这些参数导致ListView将每个子小部件子树与其他小部件包装在一起。
3> 使用AutomaticKeepAlive
控件(当addautomatickeepalives
设置为ture的时候默认会插入)。而不是向KeepAlive
一样,当滑出屏幕的无条件的缓存孩子的子树,AutomaticKeepAlive
可以让子树的派生的逻辑控制是否需要缓存该子树。
例如,EditableText
会在它有输入焦点时发送子结点子树以便保持存活状态。 如果它没有焦点,并且没有其他派生类通过KeepAliveNotification
发出保持活动的信号,则滚动选择时将清除列表子元素子树。
AutomaticKeepAlive
派生类通常使用AutomaticKeepAliveClientMixin
发信号通知它保持活动状态,然后实现wantKeepAlive
getter并调用updateKeepAlive
。
换到CustomScrollView
ListView基本上是一个CustomScrollView,在CustomScrollView.slivers属性中仅仅有一个SliverList。
如果ListView不满足需求,例如因为滚动视图既有列表又有网格,或者因为列表要与SliverAppBar等组合在一起,所以直接将代码从使用ListView移植到使用 CustomScrollView直接。
ListView上的key,scrollDirection,reverse,controller,primary,physics和shrinkWrap属性直接映射到CustomScrollView上具有相同名称的属性。
CustomScrollView.slivers属性应该是包含SliverList或SliverFixedExtentList的列表; 如果是前者,ListView上的itemExtent为null,如果是后者itemExtent不为null。
ListView上的childrenDelegate属性对应于SliverList.delegate(或SliverFixedExtentList.delegate)属性。 新的ListView构造函数的children参数对应于childrenDelegate是具有相同参数的SliverChildListDelegate。 新的ListView.builder构造函数的itemBuilder和childCount参数对应于childrenDelegate是一个带有匹配参数的SliverChildBuilderDelegate。
padding属性对应于在CustomScrollView.slivers属性中具有SliverPadding而不是列表本身,并且使SliverList成为SliverPadding的子级。
CustomScrollViews不会自动避免像ListView这样的MediaQuery障碍。 要重现该行为,请将slivers包裹在SliverSafeAreas中。
将代码移植到使用CustomScrollView后,可以将其他slivers(例如SliverGrid或SliverAppBar)放入CustomScrollView.slivers列表中。
demo
body: new ListView(
shrinkWrap: true,
padding: const EdgeInsets.all(20.0),
children: <Widget>[
const Text('I\'m dedicating every day to you'),
const Text('Domestic life was never quite my style'),
const Text('When you smile, you knock me out, I fall apart'),
const Text('And I thought I was so smart'),
],
),
image.png
body: new CustomScrollView(
shrinkWrap: true,
slivers: <Widget>[
new SliverPadding(
padding: const EdgeInsets.all(20.0),
sliver: new SliverList(
delegate: new SliverChildListDelegate(<Widget>[
const Text('I\'m dedicating every day to you'),
const Text('Domestic life was never quite my style'),
const Text('When you smile, you knock me out, I fall apart'),
const Text('And I thought I was so smart'),
const Text('I\'m dedicating every day to you'),
const Text('Domestic life was never quite my style'),
const Text('When you smile, you knock me out, I fall apart'),
const Text('And I thought I was so smart'),
])),
)
],
),
image.png
网友评论