Flutter 日记App-日记本列表页

前言

日记列表页功能:

  1. 列表信息展示
  2. 点击跳转日记本列表
  3. 设置更新日记本信息
  4. 上拉刷新,下拉加载

列表信息展示

分析:

  1. 列表页数据是动态的,需要采用builder构建列表widget,同时每个列表数据需要单独显示,也就是需要分割线,所以使用separatorBuilder。这里选择使用ListView.separated来构建列表。
  2. 列表数据展示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();
  }
}

最终效果:

相关推荐
Jouzzy2 分钟前
【iOS安全】Dopamine越狱 iPhone X iOS 16.6 (20G75) | 解决Jailbreak failed with error
安全·ios·iphone
瓜子三百克10 分钟前
采用sherpa-onnx 实现 ios语音唤起的调研
macos·ios·cocoa
肥肥呀呀呀18 分钟前
flutter使用命令生成BinarySize分析图
flutter
程序猿阿伟23 分钟前
《数字分身进化论:React Native与Flutter如何打造沉浸式虚拟形象编辑》
flutter·react native·react.js
怀君35 分钟前
Flutter——数据库Drift开发详细教程(六)
数据库·flutter
左钦杨1 小时前
IOS CSS3 right transformX 动画卡顿 回弹
前端·ios·css3
努力成为包租婆2 小时前
SDK does not contain ‘libarclite‘ at the path
ios
明似水17 小时前
2025年Flutter初级工程师技能要求
flutter
安和昂20 小时前
【iOS】Tagged Pointer
macos·ios·cocoa
程序猿阿伟20 小时前
《从像素到身份:Flutter如何打通社交应用人脸识别的技术闭环》
flutter