前言

它可以沿一个方向线性排布所有子组件,并且它也可以支持基于Sliver的延迟构建模型。

接口描述

  1. ListView({
  2. Key key,
  3. // 可滚动widget公共参数
  4. Axis scrollDirection = Axis.vertical,
  5. bool reverse = false,
  6. ScrollController controller,
  7. bool primary,
  8. ScrollPhysics physics,
  9. EdgeInsetsGeometry padding,
  10. // ListView各个构造函数的共同参数
  11. // 该参数如果不为null,则会强制children的“长度”为itemExtent的值;这里的“长度”是指滚动方向上子组件的长度,也就是说如果滚动方向是垂直方向,则itemExtent代表子组件的高度;如果滚动方向为水平方向,则itemExtent就代表子组件的宽度。在ListView中,指定itemExtent比让子组件自己决定自身长度会更高效,这是因为指定itemExtent后,滚动系统可以提前知道列表的长度,而无需每次构建子组件时都去再计算一下,尤其是在滚动位置频繁变化时(滚动系统需要频繁去计算列表高度)。
  12. this.itemExtent,
  13. // 该属性表示是否根据子组件的总长度来设置ListView的长度,默认值为false 。默认情况下,ListView的会在滚动方向尽可能多的占用空间。当ListView在一个无边界(滚动方向上)的容器中时,shrinkWrap必须为true。
  14. bool shrinkWrap = false,
  15. // 该属性表示是否将列表项(子组件)包裹在AutomaticKeepAlive 组件中;典型地,在一个懒加载列表中,如果将列表项包裹在AutomaticKeepAlive中,在该列表项滑出视口时它也不会被GC(垃圾回收),它会使用KeepAliveNotification来保存其状态。如果列表项自己维护其KeepAlive状态,那么此参数必须置为false。
  16. bool addAutomaticKeepAlives = true,
  17. // 该属性表示是否将列表项(子组件)包裹在RepaintBoundary组件中。当可滚动组件滚动时,将列表项包裹在RepaintBoundary中可以避免列表项重绘,但是当列表项重绘的开销非常小(如一个颜色块,或者一个较短的文本)时,不添加RepaintBoundary反而会更高效。和addAutomaticKeepAlive一样,如果列表项自己维护其KeepAlive状态,那么此参数必须置为false。
  18. bool addRepaintBoundaries = true,
  19. bool addSemanticIndexes = true,
  20. double cacheExtent,
  21. // 子widget列表
  22. List<Widget> children = const <Widget>[],
  23. int semanticChildCount,
  24. DragStartBehavior dragStartBehavior = DragStartBehavior.start,
  25. })

代码示例

  1. import 'package:english_words/english_words.dart';
  2. import 'package:flutter/material.dart';
  3. // ListView 默认构造函数
  4. /* 默认构造函数有一个children参数,它接受一个Widget列表(List)。这种方式适合只有少量的子组件的情况,因为这种方式需要将所有children都提前创建好(这需要做大量工作),而不是等到子widget真正显示的时候再创建,也就是说通过默认构造函数构建的ListView没有应用基于Sliver的懒加载模型。实际上通过此方式创建的ListView和使用SingleChildScrollView+Column的方式没有本质的区别。*/
  5. class ListViewTest1 extends StatelessWidget {
  6. @override
  7. Widget build(BuildContext context) {
  8. return Scaffold(
  9. appBar: AppBar(
  10. title: Text('ListView 默认构造函数'),
  11. ),
  12. body: ListView(
  13. shrinkWrap: true,
  14. padding: const EdgeInsets.all(20.0),
  15. children: <Widget>[
  16. const Text('I\'m haha'),
  17. const Text('biubiubiu`'),
  18. const Text('qiuqiuqiu`'),
  19. const Text('dindindin`'),
  20. const Text('I\'m haha'),
  21. const Text('biubiubiu`'),
  22. const Text('qiuqiuqiu`'),
  23. const Text('dindindin`'),
  24. const Text('I\'m haha'),
  25. const Text('biubiubiu`'),
  26. const Text('qiuqiuqiu`'),
  27. const Text('dindindin`'),
  28. ],
  29. ),
  30. );
  31. }
  32. }
  33. // ListView.builder
  34. /* ListView.builder适合列表项比较多(或者无限)的情况,因为只有当子组件真正显示的时候才会被创建,也就说通过该构造函数创建的ListView是支持基于Sliver的懒加载模型的。*/
  35. class ListViewTest2 extends StatelessWidget {
  36. @override
  37. Widget build(BuildContext context) {
  38. return Scaffold(
  39. appBar: AppBar(
  40. title: Text('ListView 默认构造函数'),
  41. ),
  42. body: ListView.builder(
  43. // 列表项的数量,如果为null,则为无限列表
  44. itemCount: 100,
  45. itemExtent: 50.0,
  46. itemBuilder: (BuildContext context, int index) {
  47. return ListTile(title: Text("$index"),);
  48. }
  49. )
  50. );
  51. }
  52. }
  53. // ListView.separated
  54. /*ListView.separated可以在生成的列表项之间添加一个分割组件,它比ListView.builder多了一个separatorBuilder参数,该参数是一个分割组件生成器。 */
  55. class ListViewTest3 extends StatelessWidget {
  56. Widget build(BuildContext context) {
  57. // 下划线widget预定义以供复用
  58. Widget divider1 = Divider(color: Colors.blue,);
  59. Widget divider2 = Divider(color: Colors.green,);
  60. return Scaffold(
  61. appBar: AppBar(
  62. title: Text('ListView.separated'),
  63. ),
  64. body: ListView.separated(
  65. // 列表项构造器
  66. itemBuilder: (BuildContext context, int index) {
  67. return ListTile(title: Text('$index'),);
  68. },
  69. // 分割器构造器
  70. separatorBuilder: (BuildContext context, int index) {
  71. return index%2==0?divider1:divider2;
  72. },
  73. itemCount: 100
  74. ),
  75. );
  76. }
  77. }
  78. // 实例:无限加载列表
  79. class InfiniteListView extends StatefulWidget {
  80. @override
  81. _InfiniteListViewState createState() => _InfiniteListViewState();
  82. }
  83. class _InfiniteListViewState extends State<InfiniteListView> {
  84. // 表尾标记
  85. static const loadingTag = "##loadding##";
  86. var _words = <String>[loadingTag];
  87. @override
  88. void initState() {
  89. super.initState();
  90. _retrieveData();
  91. }
  92. @override
  93. Widget build(BuildContext context) {
  94. return Scaffold(
  95. appBar: AppBar(
  96. title: Text('ListView.separated'),
  97. ),
  98. body: ListView.separated(
  99. itemBuilder: (context, index) {
  100. // 如果到了表尾
  101. if (_words[index] == loadingTag) {
  102. // 不足100条,继续获取数据
  103. if (_words.length - 1 < 100) {
  104. // 获取数据
  105. _retrieveData();
  106. // 加载时显示loading
  107. return Container(
  108. padding: const EdgeInsets.all(16.0),
  109. alignment: Alignment.center,
  110. child: SizedBox(
  111. width: 24.0,
  112. height: 24.0,
  113. child: CircularProgressIndicator(strokeWidth: 2.0,),
  114. ),
  115. );
  116. } else {
  117. // 已经加载了100条数据,不再获取数据
  118. return Container(
  119. alignment: Alignment.center,
  120. padding: EdgeInsets.all(16.0),
  121. child: Text('已经到我的底线了ฅʕ•̫͡•ʔฅ'),
  122. );
  123. }
  124. }
  125. // 显示单词列表项
  126. return ListTile(title: Text(_words[index]),);
  127. },
  128. separatorBuilder: (context, index) => Divider(height: .0,),
  129. itemCount: _words.length,
  130. ),
  131. );
  132. }
  133. // 模拟从数据源异步获取数据
  134. void _retrieveData() {
  135. Future.delayed(Duration(seconds: 2)).then((e) {
  136. _words.insertAll(
  137. _words.length - 1,
  138. // 每次生成20个单词
  139. generateWordPairs().take(20).map((e) => e.asPascalCase).toList()
  140. );
  141. setState(() {
  142. // 重新构建列表
  143. });
  144. });
  145. }
  146. }

总结

不同的构造函数对应了不同的列表项生成模型,如果需要自定义列表项生成模型,可以通过ListView.custom来自定义,它需要实现一个SliverChildDelegate用来给ListView生成列表项组件。

【Flutter】可滚动组件之ListView的更多相关文章

  1. 【Flutter学习】可滚动组件之ScrollView

    一,概述 ScrollView 是一个带有滚动的视图组件. 二,组成部分 ScrollView 由三部分组成: Scrollable - 它监听各种用户手势并实现滚动的交互设计.可滚动Widget都直 ...

  2. 【Flutter】可滚动组件之滚动控制和监听

    前言 可以用ScrollController来控制可滚动组件的滚动位置. 接口描述 ScrollController({ // 初始滚动位置 double initialScrollOffset = ...

  3. 【Flutter】可滚动组件之CustomScrollView

    前言 CustomScrollView是可以使用Sliver来自定义滚动模型(效果)的组件.它可以包含多种滚动模型,举个例子,假设有一个页面,顶部需要一个GridView,底部需要一个ListView ...

  4. 【Flutter】可滚动组件之SingleChildScrollView

    前言 SingleChildScrollView类似于Android中的ScrollView,它只能接收一个子组件. 接口描述 const SingleChildScrollView({ Key ke ...

  5. 【Flutter】可滚动组件简介

    前言 当组件内容超过当前显示视口(ViewPort)时,如果没有特殊处理,Flutter则会提示Overflow错误.为此,Flutter提供了多种可滚动组件(Scrollable Widget)用于 ...

  6. 第29讲 UI组件之 ListView与 BaseAdapter,SimpleAdapter

    第29讲 UI组件之 ListView与 BaseAdapter,SimpleAdapter 1.BaseAdapter BaseAdapter是Android应用程序中经常用到的基础数据适配器,它的 ...

  7. 第28讲 UI组件之 ListView和ArrayAdapter

    第28讲 UI组件之 ListView和ArrayAdapter 1. Adapter 适配器 Adapter是连接后端数据和前端显示的适配器接口,是数据和UI(View)之间一个重要的纽带.在常见的 ...

  8. Android常见UI组件之ListView(二)——定制ListView

    Android常见UI组件之ListView(二)--定制ListView 这一篇接上篇.展示ListView中选择多个项及实现筛选功能~ 1.在位于res/values目录下的strings.xml ...

  9. Flutter 常用组件

    无状态组件(StatelessWidget)是不可变的,这意味着它的属性不能改变,所有的值都是最终的. 有状态组件(StatefulWidget)持有的状态可能在Widget生命周期中发生变化.实现一 ...

随机推荐

  1. 原生js获取页面所有的checkbox

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. AT2688 [ARC080C] Young Maids

    一道挺有意思的题目,在这里记录一下. 题目大意 给你一个长度为 \(n\) 的排列,每一次你可以取出相邻的两个数将其放在答案序列的开头,最后问你字典序最小的答案序列是什么. 题解 由于最后是求字典序最 ...

  3. 实战演习:mysqlbinlog恢复bin-log数据

    mysqlbinlog恢复bin-log数据 Binlog日志即binary log,是二进制日志文件,有两个作用,一个是增量备份,另一个是主从复制,即从节点同步主节点数据时获取的即是bin-log, ...

  4. 记一起由 Clang 编译器优化触发的 Crash

    摘要:一个有意思的 Crash 探究过程,Clang 有 GCC 没有 本文首发于 Nebula Graph 官方博客:https://nebula-graph.com.cn/posts/troubl ...

  5. FreeSql.Repository (一)什么是仓储

    欢迎来到<FreeSql.Repository 仓储模式>系列文档,完整文档请前往 wiki 中心:https://github.com/dotnetcore/FreeSql/wiki F ...

  6. eclipse/myeclipse 使用技巧

    一.变量名自动补全 原理是:在输入变量名后,去掉按下空格或=后,代码上屏 以前只知道alt+/调出assist,后来发现可以所有字母都激活content assist(8.1里有写).用起来果然很爽, ...

  7. 04-flask-模版基础

    Jinja2 概念 Jinja2:是 Python 下一个被广泛应用的模板引擎,是由Python实现的模板语言,他的设计思想来源于 Django 的模板引擎,并扩展了其语法和一系列强大的功能,其是Fl ...

  8. SpringDataJPA 多对多的查询

     主要的结构目录: 创建Role.java package cn.itcast.domain; import javax.persistence.*; import java.util.HashSet ...

  9. openstack高可用集群17-openstack集成Ceph准备

    Openstack集成Ceph准备 Openstack环境中,数据存储可分为临时性存储与永久性存储. 临时性存储:主要由本地文件系统提供,并主要用于nova虚拟机的本地系统与临时数据盘,以及存储gla ...

  10. slice切片函数

    clc;clear all;close all; [X,Y,Z,V] = flow;x1 = min(min(min(X)));x2 = max(max(max(X)));y1 = min(min(m ...