ListView是Flutter中的列表组件,可以横向也可以垂直
ListView 常见用法
ListView 横向滚动和垂直滚动
这部分还是直接写代码吧
class ListPageState extends State<ListPage> {
bool isVertical = true;
var list = ['上海','北京','深圳','天津','邯郸',];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('测试ListView'),
),
body: ListView(
//通过该属性,设置朝向是垂直还是横向
scrollDirection: isVertical ? Axis.vertical : Axis.horizontal,
children: [
RaisedButton(
onPressed: () {
setState(() {
isVertical = !isVertical;
});
},
child: Text('点我切换方向'),
),
...buildListItem()
],
),
);
}
List<Widget> buildListItem() {
return list
.map((e) => isVertical ? _buildVItem(e) : _buildHItem(e))
.toList();
}
//构建纵向列表item
Widget _buildVItem(String cityNam) {
return Container(
margin: EdgeInsets.only(bottom: 5),
padding: EdgeInsets.only(top: 10, bottom: 10),
alignment: Alignment.center,
decoration: BoxDecoration(color: Colors.green),
child: Text(
'$cityNam',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.tealAccent),
),
);
}
//构建横向item
Widget _buildHItem(String cityNam) {
return Container(
width: 100,
height: 100,
margin: EdgeInsets.only(right: 5),
padding: EdgeInsets.only(right: 10, left: 10),
alignment: Alignment.center,
decoration: BoxDecoration(color: Colors.green),
child: Text(
'$cityNam',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.tealAccent),
),
);
}
}
效果
需要注意的是ListView横向滚动时,设置item高度是不生效的,可以设置ListView的父布局高度,进行高度控制
ListView.builder()
这是一种简便的构建ListView方式 将上面的代码简单替换即可
body: ListView.builder(
itemCount: list.length,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index) {
return _buildVItem(list[index]);
}),
可折叠的List(ExpansionTile)
实现类似QQ里面联系人分组的界面,可以使用ExpansionTile实现
class ExpandPage extends StatefulWidget {
@override
State<ExpandPage> createState() {
return ExpandPageState();
}
}
class ExpandPageState extends State<ExpandPage> {
var list = {
'中国': ['上海', '北京', '深圳', '天津', '邯郸',],
'China': ['上海', '北京', '深圳', '天津', '邯郸',],
'CN': ['上海', '北京', '深圳', '天津', '邯郸',]
};
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('测试可展开的ListView'),
),
body: ListView.builder(
itemCount: list.keys.length,
scrollDirection: Axis.vertical,
itemBuilder: (BuildContext context, int index) {
return _buildVItem(index);
}),
);
}
Widget _buildVItem(int index) {
String countyName = list.keys.elementAt(index);
var listCity = list[countyName];
return ExpansionTile(
leading: Icon(Icons.agriculture),
subtitle: Text("副标题"),
title: Text(
countyName,
style: TextStyle(fontSize: 20, color: Colors.teal),
),
children: _buildExpandItem(listCity),
);
}
List<Widget> _buildExpandItem(List<String> listCity) {
return listCity
.map((e) => FractionallySizedBox(
widthFactor: 1,
child: Container(
padding: EdgeInsets.only(top: 10, bottom: 10),
decoration: BoxDecoration(color: Colors.pink),
child: Text(
e,
style: TextStyle(fontSize: 18, color: Colors.white),
),
),
))
.toList();
}
}
效果
也可以使用ExpansionPanelList实现
GridView 网格布局
Flutter中实现网格布局使用GridView实现
- scrollDirection 控制GridView方向
- gridDelegate 控制GridView的字widget的创建方式,主轴和交叉轴方向的间距以及子widget的宽高比
- child 是子widget的list,注意改list中的widget设置的宽高是不生效的,子widget的宽高比已经由 gridDelegate 控制了
class GridPage extends StatefulWidget {
@override
State<GridPage> createState() {
return GridPageState();
}
}
class GridPageState extends State<GridPage> {
bool isVertical = true;
var list = [ '上海', '北京', '深圳', '天津', '邯郸', ];
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('测试GridView'),
),
body: GridView(
padding: EdgeInsets.all(0),//边距
scrollDirection: Axis.vertical,//是垂直滚动还是横向滚动
//GridView的子Item的创建方式
//SliverGridDelegateWithFixedCrossAxisCount :交叉轴上子widget的数量创建方式
//SliverGridDelegateWithMaxCrossAxisExtent:主轴上固定宽或高的创建方式
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,//交叉轴上子widget的数量,
mainAxisSpacing: 1,//主轴方向上子widget之间的间距
crossAxisSpacing: 1,//交叉轴方向上子widget之间的间距
childAspectRatio: 1),//子widget的交叉轴/主轴,它是宽高比或者高宽比
children: buildListItem(),
),
// body: GridView(
// padding: EdgeInsets.zero,
// scrollDirection: Axis.vertical,
// gridDelegate: SliverGridDelegateWithMaxCrossAxisExtent(
// maxCrossAxisExtent: 240,//交叉轴方向上最大宽或高
// crossAxisSpacing: 1,
// childAspectRatio: 2,
// mainAxisSpacing: 1),
// children: buildListItem(),
// ),
);
}
List<Widget> buildListItem() {
return list.map((e) => _buildVItem(e)).toList();
}
Widget _buildVItem(String cityNam) {
return Container(
padding: EdgeInsets.only(top: 10, bottom: 10),
alignment: Alignment.center,
decoration: BoxDecoration(color: Colors.green),
child: Text(
'$cityNam',
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.tealAccent),
),
);
}
}
效果
RefreshIndicator 下拉刷新组件
RefreshIndicator 是Flutter官方提供的下拉刷新组件,RefreshIndicator搭配ListView或GridView的时候 方向必须是垂直滚动的,横向的无效的,
RefreshIndicator构造分析
- onRefresh 必要参数,是返回值类型为Future的回调Future Function(),当用户下拉组件时会回调到该方法中,这个时候一般会进行http请求,数据库读写等操作,
- child 下拉刷新的子widget,一般为ListView或CustomScrollView
//模拟两秒后返回数据
Future<Null> _handRefresh() async{
await Future.delayed(Duration(seconds: 2));
setState(() {
list=list.reversed.toList();
});
}
ListView 中
GridView中
列表加载更多
Flutter官方并没有像refresh下拉刷新那样提供组件,需要通过监听列表滚动的距离是否到底部手动触发加载更多,
- 自定义ScrollController
ScrollController _scrollController;
@override
void initState() {
super.initState();
_scrollController = ScrollController();
_scrollController.addListener(() {
if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) {
print("开始加载更多");
_handLoadMore();
}
});
}
- 触发加载更多
_handLoadMore() async {
await Future.delayed(Duration(seconds: 15));
setState(() {
var newData = List<String>.from(list);
list.addAll(newData);
});
}
- 将Scroller设置给ListView
ListView( controller: _scrollController,XXX)
如果上下反复滚动会多次触发该方法,需要自定义状态进行加载更多的控制
今天的文章Flutter学习7-列表ListView用法(横向滚动,下拉刷新,上拉加载)分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/16341.html