Flutter 流式布局列表实例+上拉加载

2022-12-01,,,,

页面变化的几种方式:

一、StatefulWidget的setState形式

先声明两个变量。

int page = ;
List<Map> list = [];

写了一个方法,获取数据:

void _getHotGoods(){
var formData = {'page':page};
request('post', 'homePageBelowConten',formData: formData).then((val){
var data = json.decode(val.toString());
List<Map> newList = (data['data'] as List).cast();
setState(() {
list.addAll(newList); //新的列表加到老的列表之上
page ++;
});
});
}

然后实现页面布局

标题:

//火爆专区标题 变量的形式
Widget hotTitle = Container(
margin: EdgeInsets.only(top: 10.0),
alignment: Alignment.center,
color: Colors.transparent, //透明背景色
padding: EdgeInsets.all(5.0),
child: Text('火爆专区'),
);

每个子项:

//火爆专区子项 方法的形式
Widget _wrapList(){
if(list.length != ){
List<Widget> listWidget = list.map((val){ //把Map类型的List包装成Widget,再放回List里,并赋值给流式布局
return InkWell(
onTap: (){},
child: Container(
width: ScreenUtil().setWidth(),
color: Colors.white,
padding: EdgeInsets.all(5.0),
margin: EdgeInsets.only(bottom: 3.0),
child: Column(
children: <Widget>[
Image.network(val['image'],width:ScreenUtil().setWidth()),
Text(
val['name'],
maxLines: ,
overflow:TextOverflow.ellipsis,
style:TextStyle(color:Colors.blueGrey,fontSize:ScreenUtil().setSp()),
),
Row(
children: <Widget>[
Text('¥${val['mallPrice']}'),
Text(
'¥${val['price']}',
style: TextStyle(color: Colors.black26,decoration: TextDecoration.lineThrough),
)
],
),
],
),
),
);
}).toList(); //把Map类型的List包装成Widget,再放回List里,并赋值给流式布局 return Wrap( //返回流式布局
spacing: , //每行2列
children: listWidget,
);
}else{
return Text(''); //没有数据时返回空
}
}

组合在一起:

//火爆专区组合
Widget _hotGoods(){
return Container(
child: Column(
children: <Widget>[
hotTitle,
_wrapList(),
],
),
);
}

完整代码:

import 'package:flutter/material.dart';
import '../service/service_method.dart';
import 'dart:convert';
import 'package:flutter_screenutil/flutter_screenutil.dart'; class CategoryPage extends StatefulWidget { _CategoryPageState createState() => _CategoryPageState();
} class _CategoryPageState extends State<CategoryPage> {
int page = ;
List<Map> list = []; @override
void initState() {
super.initState();
_getHotGoods(); //火爆专区获取值
} @override
Widget build(BuildContext context) {
return SingleChildScrollView(
child:Column(
children: <Widget>[
_hotGoods(),
],
),
);
} //火爆商品接口
void _getHotGoods(){
var formData = {'page':page}; //Map类型
request('post', 'homePageBelowConten',formData: formData).then((val){
var data = json.decode(val.toString());
List<Map> newList = (data['data'] as List).cast();
setState(() {
list.addAll(newList); //新的列表加到老的列表之上
page ++;
});
});
}
//火爆专区标题 变量的形式
Widget hotTitle = Container(
margin: EdgeInsets.only(top: 10.0),
alignment: Alignment.center,
color: Colors.transparent, //透明背景色
padding: EdgeInsets.all(5.0),
child: Text('火爆专区'),
);
//火爆专区子项 方法的形式
Widget _wrapList(){
if(list.length != ){
List<Widget> listWidget = list.map((val){ //Map循环的形式:把Map类型的List包装成Widget,再放回List里,并赋值给流式布局
return InkWell(
onTap: (){},
child: Container(
width: ScreenUtil().setWidth(),
color: Colors.white,
padding: EdgeInsets.all(5.0),
margin: EdgeInsets.only(bottom: 3.0),
child: Column(
children: <Widget>[
Image.network(val['image'],width:ScreenUtil().setWidth()),
Text(
val['name'],
maxLines: ,
overflow:TextOverflow.ellipsis,
style:TextStyle(color:Colors.blueGrey,fontSize:ScreenUtil().setSp()),
),
Row(
children: <Widget>[
Text('¥${val['mallPrice']}'),
Text(
'¥${val['price']}',
style: TextStyle(color: Colors.black26,decoration: TextDecoration.lineThrough),
)
],
),
],
),
),
);
}).toList(); //Map循环的形式:把Map类型的List包装成Widget,再放回List里,并赋值给流式布局 return Wrap( //返回流式布局
spacing: , //每行2列
children: listWidget,
);
}else{
return Text(''); //没有数据时返回空
}
}
//火爆专区组合
Widget _hotGoods(){
return Container(
child: Column(
children: <Widget>[
hotTitle,
_wrapList(),
],
),
);
} }

flutter_easyrefresh插件:

EasyRefresh很容易就能在Flutter应用上实现下拉刷新以及上拉加载操作,它支持几乎所有的Flutter控件,但前提是需要包裹成ScrollView。它的功能与Android的SmartRefreshLayout很相似,同样也吸取了很多三方库的优点。EasyRefresh中集成了多种风格的Header和Footer,但是它并没有局限性,你可以很轻松的自定义。使用Flutter强大的动画,甚至随便一个简单的控件也可以完成。EasyRefresh的目标是为Flutter打造一个强大,稳定,成熟的下拉刷新框架。

github:https://github.com/xuelongqy/flutter_easyrefresh

flutter_easyrefresh优点:

能够自定义酷炫的Header和Footer,也就是上拉和下拉的效果。
更新及时,不断在完善,录课截至时已经是v1.2.7版本了。
有一个辅导群,虽然文档不太完善,但是有辅导群和详细的案例。
回掉方法简单,这个具体可以看下面的例子。

引入依赖

直接在pubspec.yaml中的dependencies中进行引入,主要要用最新版本,文章中的版本不一定是最新版本。

flutter_easyrefresh: ^1.2.7

引入后,在要使用的页面用import引入package,代码如下:

import 'package:flutter_easyrefresh/easy_refresh.dart';

制作上拉加载效果

使用这个插件,要求我们必须是一个ListView,所以我们要改造以前的代码,SingleChildScrollView改造成ListView。并添加loadMore,把_getHotGoods的内容粘贴过来,

_getHotGoods();就可以注掉了。

return EasyRefresh(
child:ListView(
children: <Widget>[
_hotGoods(),
],
),
loadMore: () async{
var formData = {'page':page}; //Map类型
await request('post', 'homePageBelowConten',formData: formData).then((val){
var data = json.decode(val.toString());
List<Map> newList = (data['data'] as List).cast();
setState(() {
list.addAll(newList); //新的列表加到老的列表之上
page ++;
});
});
},
);

现在运行已经可以看到效果了,不过还需要修改下。

自定义上拉加载效果

因为它自带的样式是蓝色的,与我们的界面不太相符,所以我们改造一下,它的底部上拉刷新效果。如果你有兴趣做出更炫酷的效果,可以自行查看一下Github,学习一下。

    refreshFooter:ClassicsFooter( //自定义上拉加载效果
key:_footerKey,
bgColor:Colors.white,
textColor: Colors.blueGrey,
moreInfoColor: Colors.blueGrey,
showMore: true,
noMoreText: '',
moreInfo: '加载中', //加载时显示的文字
loadReadyText: '上拉加载...', //准备时显示的文字
),

还要在上面定义Key:

GlobalKey<RefreshFooterState> _footerKey = new GlobalKey<RefreshFooterState>(); //定义key

完整代码:

import 'package:flutter/material.dart';
import '../service/service_method.dart';
import 'dart:convert';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:flutter_easyrefresh/easy_refresh.dart'; class CategoryPage extends StatefulWidget { _CategoryPageState createState() => _CategoryPageState();
} class _CategoryPageState extends State<CategoryPage> {
int page = ;
List<Map> list = []; GlobalKey<RefreshFooterState> _footerKey = new GlobalKey<RefreshFooterState>(); //定义key @override
void initState() {
super.initState();
//_getHotGoods(); //火爆专区获取值
} @override
Widget build(BuildContext context) {
return EasyRefresh(
refreshFooter:ClassicsFooter( //自定义上拉加载效果
key:_footerKey,
bgColor:Colors.white,
textColor: Colors.blueGrey,
moreInfoColor: Colors.blueGrey,
showMore: true,
noMoreText: '',
moreInfo: '加载中', //加载时显示的文字
loadReadyText: '上拉加载...', //准备时显示的文字
),
child:ListView(
children: <Widget>[
_hotGoods(),
],
),
loadMore: () async{
var formData = {'page':page}; //Map类型
await request('post', 'homePageBelowConten',formData: formData).then((val){
var data = json.decode(val.toString());
List<Map> newList = (data['data'] as List).cast();
setState(() {
list.addAll(newList); //新的列表加到老的列表之上
page ++;
});
});
},
);
} //火爆商品接口
// void _getHotGoods(){
// var formData = {'page':page}; //Map类型
// request('post', 'homePageBelowConten',formData: formData).then((val){
// var data = json.decode(val.toString());
// List<Map> newList = (data['data'] as List).cast();
// setState(() {
// list.addAll(newList); //新的列表加到老的列表之上
// page ++;
// });
// });
// }
//火爆专区标题 变量的形式
Widget hotTitle = Container(
margin: EdgeInsets.only(top: 10.0),
alignment: Alignment.center,
color: Colors.transparent, //透明背景色
padding: EdgeInsets.all(5.0),
child: Text('火爆专区'),
);
//火爆专区子项 方法的形式
Widget _wrapList(){
if(list.length != ){
List<Widget> listWidget = list.map((val){ //Map循环的形式:把Map类型的List包装成Widget类型,再放回List里,并赋值给流式布局
return InkWell(
onTap: (){},
child: Container(
width: ScreenUtil().setWidth(),
color: Colors.white,
padding: EdgeInsets.all(5.0),
margin: EdgeInsets.only(bottom: 3.0),
child: Column(
children: <Widget>[
Image.network(val['image'],width:ScreenUtil().setWidth()),
Text(
val['name'],
maxLines: ,
overflow:TextOverflow.ellipsis,
style:TextStyle(color:Colors.blueGrey,fontSize:ScreenUtil().setSp()),
),
Row(
children: <Widget>[
Text('¥${val['mallPrice']}'),
Text(
'¥${val['price']}',
style: TextStyle(color: Colors.black26,decoration: TextDecoration.lineThrough),
)
],
),
],
),
),
);
}).toList(); //Map循环的形式:把Map类型的List包装成Widget类型,再放回List里,并赋值给流式布局 return Wrap( //返回流式布局
spacing: , //每行2列
children: listWidget,
);
}else{
return Text(''); //没有数据时返回空
}
}
//火爆专区组合
Widget _hotGoods(){
return Container(
child: Column(
children: <Widget>[
hotTitle,
_wrapList(),
],
),
);
} }

Flutter 流式布局列表实例+上拉加载的相关教程结束。

《Flutter 流式布局列表实例+上拉加载.doc》

下载本文的Word格式文档,以方便收藏与打印。