前言
日记列表页功能:
- 列表信息展示
- 点击跳转日记本列表
- 设置更新日记本信息
- 上拉刷新,下拉加载
列表信息展示
分析:
- 列表页数据是动态的,需要采用builder构建列表widget,同时每个列表数据需要单独显示,也就是需要分割线,所以使用separatorBuilder。这里选择使用ListView.separated来构建列表。
- 列表数据展示cell,这里将cell进行封装使用。
先来第一步,构建列表:
php
body: ListView.separated(
itemCount: dreamList.length,
itemBuilder: (BuildContext context, int index){
//封装的cell,将日记本数据模型传入
return DreamListCell(dream: dreamList[index]);
},
separatorBuilder: (BuildContext context, int index){
//分割线
return const Divider(
height: 1,
color: SSLUIManager.dividerLight,
);
},
),
第二步和第三步一起,封装DreamListCell。
cell 中标题和副标题不确定长度,需要自适应显示,且最多仅显示两行。
less
Widget build(BuildContext context) {
return GestureDetector(//添加手势,点击cell进入日记列表
child: Container(
color: sslUI.cellBackColor,
child: Column(
children: [
Padding(
padding: const EdgeInsets.only(left: 15, top: 10, right: 15),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
//控制标题的高度
SizedBox(
height: 35,//获取当前屏幕的宽,右边留位置给更新按钮
width: MediaQuery.of(context).size.width - 80,
child: Text(dreamInfo.title, style: TextStyle(color: sslUI.mainText, fontSize: 16), maxLines: 2,overflow: TextOverflow.ellipsis,),//文本显示设置
),
//控制按钮大小
SizedBox(
width: 40,
height: 40,
//右边更新按钮
child: IconButton(
alignment: Alignment.topRight,
padding: EdgeInsets.zero,
onPressed: ()async{
点击进入更新列表,更新完成后返回最新的日记本信息
dreamInfo = await Get.toNamed(SSLRoutes.home_add_dream,arguments: dreamInfo);
setState(() {
});
},
icon: Icon(Icons.settings, color: sslUI.iconColor,)
),
),
],
),
),
//副标题和时间弹性显示
Flex(
direction: Axis.horizontal,
children: [
Expanded(
flex: 3,
child: Padding(
padding: const EdgeInsets.only(left: 15, top: 0, bottom: 10),
child: Text(dreamInfo.subTitle, style: TextStyle(color: sslUI.subText),maxLines: 2, overflow: TextOverflow.ellipsis,),
),
),
Expanded(
flex: 2,
child: Padding(
padding: const EdgeInsets.only(right: 15, top: 0, bottom: 10,left: 10),
child: Text(dreamInfo.getLastTimeStr(),textAlign: TextAlign.right, style: TextStyle(color: sslUI.subText),maxLines: 2,overflow: TextOverflow.clip,),
)
),
],
),
],
)
),
onTap: (){
//手势单击进入日记列表
clickAction();
},
);
}
void clickAction(){
Get.toNamed(SSLRoutes.home_RecordList,arguments: dreamInfo.dreamId);
}
第四步,添加上拉刷新和下拉加载
这里采用三方库 easy_refresh来实现。 最终代码:
scss
class SSLHomeState extends State <SSLHome> with AutomaticKeepAliveClientMixin{
late EasyRefreshController _easeController;
late List<DreamModel> dreamList;
@override
void initState() {
// TODO: implement initState
super.initState();
_easeController = EasyRefreshController(
controlFinishLoad: true,
controlFinishRefresh: true,
);
dreamList = [];
loadDataAction();
}
@override
bool get wantKeepAlive => true;
@override
Widget build(BuildContext context) {
super.build(context);
// TODO: implement build
return Scaffold(
// backgroundColor: sslUI.scrollBgColor,
appBar: AppBar(
title: Text(SSLLocales.main_tab_home.tr),
actions: [
IconButton(
onPressed: () async{
int result = await Get.toNamed(SSLRoutes.home_add_dream, arguments: null);
debugPrint('ssl current $result');
if (result > 0){
loadDataAction();
}
},
icon: Icon(Icons.add_circle,color: sslUI.iconColor,)
)
],
),
body: EasyRefresh(
onLoad: () async {
// List<DreamModel> lists = await sslDB.selectDream();
// debugPrint("Start refresh data $lists\n");
},
onRefresh: ()async {
loadDataAction();
},
header: const ClassicHeader(),
footer: const ClassicFooter(),
child: ListView.separated(
itemCount: dreamList.length,
itemBuilder: (BuildContext context, int index){
return DreamListCell(dream: dreamList[index]);
},
separatorBuilder: (BuildContext context, int index){
return const Divider(
height: 1,
color: SSLUIManager.dividerLight,
);
},
),
),
);
}
// Future<List<DreamModel>> 下拉加载数据
void loadDataAction() async{
List<DreamModel> lists = await sslDB.selectDream();
debugPrint("Start load data $lists\n");
dreamList = [];
dreamList.insertAll(0, lists);
setState(() {
});
// return lists;
}
@override
void dispose() {
//移除后销毁刷新控制器
// TODO: implement dispose
_easeController.dispose();
super.dispose();
}
}
最终效果: