一、 ListView默认构造方法
ListView({
//可滚动widget公共参数
Key key,
Axis scrollDirection = Axis.vertical, //设置滑动方向 Axis.horizontal 水平 默认 Axis.vertical 垂直
bool reverse = false, //是否倒序显示 默认正序 false 倒序true
ScrollController controller, //滑动监听
bool primary, //false,如果内容不足,则用户无法滚动 而如果[primary]为true,它们总是可以尝试滚动。
ScrollPhysics physics, //滑动类型设置:physics: new ClampingScrollPhysics(),
bool shrinkWrap = false, //内容适配
EdgeInsetsGeometry padding, //内间距:padding: EdgeInsets.all(10.0),
//ListView各个构造函数的共同参数
this.itemExtent, //确定每一个item的高度 会让item加载更加高效
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent, //设置预加载的区域
//子widget列表
List<Widget> children = const <Widget>[],
int semanticChildCount,
DragStartBehavior dragStartBehavior = DragStartBehavior.start,
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
})
1. scrollDirection :
滚动方向。默认是vertical,垂直滚动。
2. reverse:
是否与设置的滚动方向相反的方向滚动。默认是 false
3. controller:
滑动监听,我们多用于上拉加载更多,通过监听滑动的距离来执行操作。
此属性接受一个ScrollController对象。ScrollController的主要作用是控制滚动位置和监听滚动事件。
默认情况下,Widget树中会有一个默认的PrimaryScrollController,
如果子树中的可滚动组件没有显式的指定controller,
并且primary属性值为true时(默认就为true),可滚动组件会使用这个默认的PrimaryScrollController。
这种机制带来的好处是父组件可以控制子树中可滚动组件的滚动行为,
例如,Scaffold正是使用这种机制在iOS中实现了点击导航栏回到顶部的功能。
4. primary:
指是否使用widget树中默认的PrimaryScrollController;
当滑动方向为垂直方向(scrollDirection值为Axis.vertical)并且没有指定controller时,
primary默认为true.
在构造中默认是false 它的意思就是为主的意思,primary为true时,我们的controller 滑动监听就不能使用了
5. physics:
此属性接受一个ScrollPhysics类型的对象,它决定可滚动组件如何响应用户操作,
比如用户滑动完抬起手指后,继续执行动画;或者滑动到边界时,如何显示。
默认情况下,Flutter会根据具体平台分别使用不同的ScrollPhysics对象,
应用不同的显示效果,如当滑动到边界时,继续拖动的话,在iOS上会出现弹性效果,
而在Android上会出现微光效果。如果你想在所有平台下使用同一种效果,
可以显式指定一个固定的ScrollPhysics,Flutter SDK中包含了两个ScrollPhysics的子类,
他们可以直接使用:
这个属性几个滑动的选择
AlwaysScrollableScrollPhysics() 总是可以滑动
NeverScrollableScrollPhysics 禁止滚动
BouncingScrollPhysics 内容超过一屏 上拉有回弹效果(iOS下弹性效果)
ClampingScrollPhysics 包裹内容 不会有回弹(Android下微光效果)
6. shrinkWrap:
该属性表示是否根据子组件的总长度来设置ListView的长度,默认值为false 。
默认情况下,ListView的会在滚动方向尽可能多的占用空间。
当ListView在一个无边界(滚动方向上)的容器中时,shrinkWrap必须为true。
child 高度会适配 item填充的内容的高度,我们非常的不希望child的高度固定,
因为这样的话,如果里面的内容超出就会造成布局的溢出。
shrinkWrap多用于嵌套listView中 内容大小不确定 比如 垂直布局中 先后放入文字 listView
(需要Expend包裹否则无法显示无穷大高度
但是需要确定listview高度 shrinkWrap使用内容适配不会有这样的影响)
7. padding:
ListView的内边距。padding: const EdgeInsets.all(16.0),
8. itemExtent:
该参数如果不为null,则会强制children的“长度”为itemExtent的值;
这里的“长度”是指滚动方向上子组件的长度,也就是说如果滚动方向是垂直方向,
则itemExtent代表子组件的高度;如果滚动方向为水平方向,则itemExtent就代表子组件的宽度。
在ListView中,指定itemExtent比让子组件自己决定自身长度会更高效,这是因为指定itemExtent后,
滚动系统可以提前知道列表的长度,而无需每次构建子组件时都去再计算一下,
尤其是在滚动位置频繁变化时(滚动系统需要频繁去计算列表高度)。
9. addAutomaticKeepAlives:
该属性表示是否将列表项(子组件)包裹在AutomaticKeepAlive 组件中;
典型地,在一个懒加载列表中,如果将列表项包裹在AutomaticKeepAlive中,
在该列表项滑出视口时它也不会被GC(垃圾回收),它会使用KeepAliveNotification来保存其状态。
如果列表项自己维护其KeepAlive状态,那么此参数必须置为false。
10. addRepaintBoundaries:
该属性表示是否将列表项(子组件)包裹在RepaintBoundary组件中。
当可滚动组件滚动时,将列表项包裹在RepaintBoundary中可以避免列表项重绘,
但是当列表项重绘的开销非常小(如一个颜色块,或者一个较短的文本)时,
不添加RepaintBoundary反而会更高效。和addAutomaticKeepAlive一样,
如果列表项自己维护其KeepAlive状态,那么此参数必须置为false。
11. cacheExtent:
这个属性的意思就是预加载的区域
设置预加载的区域 cacheExtent 强制设置为了 0.0,从而关闭了“预加载”
二、ListView.builder
ListView.builder({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
this.itemExtent,
@required IndexedWidgetBuilder itemBuilder,
int itemCount,//item 数量
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
int semanticChildCount,
DragStartBehavior dragStartBehavior = DragStartBehavior.start,
})
1. itemBuilder:
它是列表项的构建器,类型为IndexedWidgetBuilder,返回值为一个widget。
当列表滚动到具体的index位置时,会调用该构建器构建列表项。
2. itemCount:
列表项的数量,如果为null,则为无限列表。
三、ListView.separated
ListView.separated({
Key key,
Axis scrollDirection = Axis.vertical,
bool reverse = false,
ScrollController controller,
bool primary,
ScrollPhysics physics,
bool shrinkWrap = false,
EdgeInsetsGeometry padding,
@required IndexedWidgetBuilder itemBuilder,
@required IndexedWidgetBuilder separatorBuilder,
@required int itemCount,
bool addAutomaticKeepAlives = true,
bool addRepaintBoundaries = true,
bool addSemanticIndexes = true,
double cacheExtent,
ScrollViewKeyboardDismissBehavior keyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.manual,
})
四、ListTile
const ListTile({
Key key,
this.leading, // 前置图标
this.title, //标题
this.subtitle, //副标题
this.trailing, //后置图标
this.isThreeLine = false, //是否三行显示
this.dense, //整体大小
this.contentPadding, //内容内边距
this.enabled = true,
this.onTap, //点击事件
this.onLongPress, //长按事件
this.selected = false, //是否选中状态
})
示例代码:
import 'package:flutter/material.dart';
class ListTestPage extends StatefulWidget {
@override
_ListTestPageState createState() => _ListTestPageState();
}
class _ListTestPageState extends State<ListTestPage> {
@override
Widget build(BuildContext context) {
List<Widget> _list = new List();
for (int i = 0; i < titleList.length; i++) {
_list.add(
buildListData(context, titleList[i], iconList[i], subTitleList[i]));
}
// 分割线
var divideTitles =
ListTile.divideTiles(context: context, tiles: _list).toList();
return Scaffold(
appBar: AppBar(
title: Text('List Test Page'),
),
body: Scrollbar(
// child: listView(_list),
// child: listViewBuilder(),
child: listViewSeparated(),
),
);
}
///默认构造方法
Widget listView(List<Widget> _list) {
return ListView(
children: _list,
);
}
/// ListView.builder
Widget listViewBuilder() {
return ListView.builder(
//无分割线
// itemBuilder: (context, i) {
// return buildListData(
// context, titleList[i], iconList[i], subTitleList[i]);
// },
//有分割线
itemBuilder: (context, i) {
return Container(
child: Column(
children: <Widget>[
buildListData(
context, titleList[i], iconList[i], subTitleList[i]),
Divider(),
],
),
);
},
itemCount: titleList.length,
);
}
///ListView.separated
Widget listViewSeparated() {
return ListView.separated(
itemBuilder: (context, i) {
return buildListData(
context, titleList[i], iconList[i], subTitleList[i]);
},
separatorBuilder: (BuildContext context, int index) {
return Divider();
},
itemCount: titleList.length);
}
Widget buildListData(BuildContext context, String titleItem, Icon iconItem,
String subTitleItem) {
return ListTile(
leading: iconItem,
title: Text(
titleItem,
style: TextStyle(fontSize: 18.0),
),
subtitle: Text(
subTitleItem,
),
trailing: Icon(Icons.keyboard_arrow_right),
onTap: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
'ListViewAlert',
style: TextStyle(
color: Colors.black54,
fontSize: 18.0,
),
),
content: Text('选择的item内容为:$titleItem'),
);
},
);
},
);
}
//数据源
List<String> titleList = <String>[
'北京市',
'天津市',
'河北省',
'山西省',
'内蒙古自治区',
'辽宁省',
'吉林省',
'黑龙江省',
'上海市',
'江苏省',
'浙江省',
'安徽省',
'江西省',
'山东省'
];
List<Icon> iconList = <Icon>[
Icon(Icons.keyboard),
Icon(Icons.print),
Icon(Icons.router),
Icon(Icons.pages),
Icon(Icons.zoom_out_map),
Icon(Icons.zoom_out),
Icon(Icons.youtube_searched_for),
Icon(Icons.wifi_tethering),
Icon(Icons.wifi_lock),
Icon(Icons.widgets),
Icon(Icons.weekend),
Icon(Icons.web),
Icon(Icons.accessible),
Icon(Icons.ac_unit),
];
List<String> subTitleList = [
'简称:京',
'简称:津',
'简称:冀',
'简称:晋',
'简称:内蒙古',
'简称:辽',
'简称:吉',
'简称:黑',
'简称:沪',
'简称:苏',
'简称:浙',
'简称:皖',
'简称:赣',
'简称:鲁',
];
}
效果图如下: