{"id":19273020,"url":"https://github.com/fluttercandies/loading_more_list","last_synced_at":"2025-04-09T05:09:31.712Z","repository":{"id":42186806,"uuid":"170713045","full_name":"fluttercandies/loading_more_list","owner":"fluttercandies","description":"A loading more list which supports ListView,GridView,WaterfallFlow and Slivers.","archived":false,"fork":false,"pushed_at":"2024-09-25T06:17:39.000Z","size":3955,"stargazers_count":370,"open_issues_count":4,"forks_count":48,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-02T04:02:31.074Z","etag":null,"topics":["flutter","load-more","pull-up-refresh","sliverlist","waterfall-flow"],"latest_commit_sha":null,"homepage":"","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/fluttercandies.png","metadata":{"files":{"readme":"README-ZH.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":"CODEOWNERS","security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"custom":"http://zmtzawqlp.gitee.io/my_images/images/qrcode.png"}},"created_at":"2019-02-14T15:26:44.000Z","updated_at":"2025-03-01T06:48:42.000Z","dependencies_parsed_at":"2024-06-18T17:10:58.598Z","dependency_job_id":"2019dacf-7d87-4e2c-b88e-caff580f3aad","html_url":"https://github.com/fluttercandies/loading_more_list","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttercandies%2Floading_more_list","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttercandies%2Floading_more_list/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttercandies%2Floading_more_list/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fluttercandies%2Floading_more_list/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fluttercandies","download_url":"https://codeload.github.com/fluttercandies/loading_more_list/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247980837,"owners_count":21027808,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["flutter","load-more","pull-up-refresh","sliverlist","waterfall-flow"],"created_at":"2024-11-09T20:40:04.212Z","updated_at":"2025-04-09T05:09:31.692Z","avatar_url":"https://github.com/fluttercandies.png","language":"Dart","readme":"# loading_more_list\n\n加载更多列表支持ListView,GridView以及瀑布流。\n\n[![pub package](https://img.shields.io/pub/v/loading_more_list.svg)](https://pub.dartlang.org/packages/loading_more_list) [![GitHub stars](https://img.shields.io/github/stars/fluttercandies/loading_more_list)](https://github.com/fluttercandies/loading_more_list/stargazers) [![GitHub forks](https://img.shields.io/github/forks/fluttercandies/loading_more_list)](https://github.com/fluttercandies/loading_more_list/network)  [![GitHub license](https://img.shields.io/github/license/fluttercandies/loading_more_list)](https://github.com/fluttercandies/loading_more_list/blob/master/LICENSE)  [![GitHub issues](https://img.shields.io/github/issues/fluttercandies/loading_more_list)](https://github.com/fluttercandies/loading_more_list/issues) \u003ca target=\"_blank\" href=\"https://jq.qq.com/?_wv=1027\u0026k=5bcc0gy\"\u003e\u003cimg border=\"0\" src=\"https://pub.idqqimg.com/wpa/images/group.png\" alt=\"flutter-candies\" title=\"flutter-candies\"\u003e\u003c/a\u003e\n\n[掘金社区文章](https://juejin.im/post/5bfb9cb7e51d45592b766769)\n\n语言: [English](README.md) | 中文简体\n\n[Web demo for LoadingMoreList](https://fluttercandies.github.io/loading_more_list/)\n\n- [loading_more_list](#loading_more_list)\n  - [使用](#使用)\n  - [准备数据源](#准备数据源)\n  - [参数](#参数)\n  - [Widget](#widget)\n  - [ListView](#listview)\n  - [GridView](#gridview)\n  - [瀑布流](#瀑布流)\n  - [Sliver/CustomScrollView](#slivercustomscrollview)\n  - [状态效果](#状态效果)\n  - [内存回收](#内存回收)\n  - [可视区域追踪](#可视区域追踪)\n  - [LastChildLayoutType](#lastchildlayouttype)\n  - [CloseToTrailing](#closetotrailing)\n  - [☕️Buy me a coffee](#️buy-me-a-coffee)\n\n## 使用\n\n* 添加库到 pubspec.yaml\n\n```yaml\n\ndependencies:\n  loading_more_list: any\n\n```\n* 导入库\n\n```dart\n\n  import 'package:loading_more_list/loading_more_list.dart';\n\n```\n\n## 准备数据源\n\n你需要继承LoadingMoreBase\u003cT\u003e来实现加载更多的数据源. 通过重写loadData方法来加载数据. 当没有数据的时候记得把hasMore设置为false.\n\n```dart\nclass TuChongRepository extends LoadingMoreBase\u003cTuChongItem\u003e {\n  int pageindex = 1;\n  bool _hasMore = true;\n  bool forceRefresh = false;\n  @override\n  bool get hasMore =\u003e (_hasMore \u0026\u0026 length \u003c 30) || forceRefresh;\n\n  @override\n  Future\u003cbool\u003e refresh([bool clearBeforeRequest = false]) async {\n    _hasMore = true;\n    pageindex = 1;\n    //force to refresh list when you don't want clear list before request\n    //for the case, if your list already has 20 items.\n    forceRefresh = !clearBeforeRequest;\n    var result = await super.refresh(clearBeforeRequest);\n    forceRefresh = false;\n    return result;\n  }\n\n  @override\n  Future\u003cbool\u003e loadData([bool isloadMoreAction = false]) async {\n    String url = \"\";\n    if (this.length == 0) {\n      url = \"https://api.tuchong.com/feed-app\";\n    } else {\n      int lastPostId = this[this.length - 1].postId;\n      url =\n          \"https://api.tuchong.com/feed-app?post_id=$lastPostId\u0026page=$pageindex\u0026type=loadmore\";\n    }\n    bool isSuccess = false;\n    try {\n      //to show loading more clearly, in your app,remove this\n      await Future.delayed(Duration(milliseconds: 500));\n\n      var result = await HttpClientHelper.get(url);\n\n      var source = TuChongSource.fromJson(json.decode(result.body));\n      if (pageindex == 1) {\n        this.clear();\n      }\n      for (var item in source.feedList) {\n        if (item.hasImage \u0026\u0026 !this.contains(item) \u0026\u0026 hasMore) this.add(item);\n      }\n\n      _hasMore = source.feedList.length != 0;\n      pageindex++;\n      isSuccess = true;\n    } catch (exception, stack) {\n      isSuccess = false;\n      print(exception);\n      print(stack);\n    }\n    return isSuccess;\n  }\n}\n\n```\n\n## 参数\n\n大部分参数都跟官方列表一样.\n\n下面的参数是为加载更多而设计的.\n\nListConfig\u003cT\u003e 和 SliverListConfig\u003cT\u003e\n\n| 参数                 | 描述                                          | 默认                     |\n| -------------------- | --------------------------------------------- | ------------------------ |\n| itemBuilder          | 列表元素构建器.                               | 必填                     |\n| sourceList           | 数据源继承于LoadingMoreBase\u003cT\u003e.               | 必填                     |\n| showGlowLeading      | 是否显示过度拖拽上部波纹.                     | 0.0                      |\n| showGlowTrailing     | 是否显示过度拖拽下部波纹.                     | -                        |\n| lastChildLayoutType  | 最后一个元素的布局样式(loadmore/no more元素). | LastChildLayoutType.foot |\n| extendedListDelegate | WaterfallFlow 或者 ExtendedList的委托         | -                        |\n| gridDelegate         | GridView定义委托.                             | -                        |\n| indicatorBuilder     | 状态指示构建器.                               | IndicatorWidget          |\n| padding              | 边距，SliverListConfig\u003cT\u003e的参数               | -                        |\n| childCountBuilder    | 动态获取 child count的回调,入参为列表的长度   | -                        |\n\n## Widget\n\nLoadingMoreList\u003cT\u003e\n\n| 参数                 | 描述                   | 默认     |\n| -------------------- | ---------------------- | -------- |\n| listConfig           | ListConfig\u003cT\u003e 构建参数 | required |\n| onScrollNotification | 获取滚动冒泡通知.      | -        |\n\nLoadingMoreSliverList\u003cT\u003e\n\n| 参数             | 描述                         | 默认     |\n| ---------------- | ---------------------------- | -------- |\n| sliverListConfig | SliverListConfig\u003cT\u003e 构建参数 | required |\n\nLoadingMoreCustomScrollView\n\n| 参数                    | 描述                                                                      | 默认  |\n| ----------------------- | ------------------------------------------------------------------------- | ----- |\n| onScrollNotification    | 获取滚动冒泡通知.                                                         | -     |\n\n\n## ListView\n\n![](https://github.com/fluttercandies/Flutter_Candies/tree/master/gif/loading_moe_list/listview.gif)\n\n```dart\n            LoadingMoreList(\n              ListConfig\u003cTuChongItem\u003e(\n                itemBuilder: ItemBuilder.itemBuilder,\n                sourceList: listSourceRepository,\n                padding: EdgeInsets.all(0.0),\n              ),\n            ),\n```\n\n## GridView\n\n通过gridDelegate定义GridView\n\n```dart\n            LoadingMoreList(\n              ListConfig\u003cTuChongItem\u003e(\n                itemBuilder: ItemBuilder.itemBuilder,\n                sourceList: listSourceRepository,\n                padding: EdgeInsets.all(0.0),\n                gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(\n                  crossAxisCount: 2,\n                  crossAxisSpacing: 3.0,\n                  mainAxisSpacing: 3.0,\n                ),\n              ),\n            ),\n```\n\n## 瀑布流\n\n![](https://github.com/fluttercandies/Flutter_Candies/tree/master/gif/waterfall_flow/known_sized.gif)\n\n通过waterfallFlowDelegate定义瀑布流\n\n```dart\n            LoadingMoreList(\n              ListConfig\u003cTuChongItem\u003e(\n                extendedListDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(\n                  crossAxisCount: 2,\n                  crossAxisSpacing: 5,\n                  mainAxisSpacing: 5,\n                ),\n                itemBuilder: _buildItem,\n                sourceList: listSourceRepository,\n                padding: EdgeInsets.all(5.0),\n              ),\n            ),\n```\n\n## Sliver/CustomScrollView\n\n| ![](https://github.com/fluttercandies/Flutter_Candies/tree/master/gif/loading_moe_list/multiple_sliver.gif) | ![](https://github.com/fluttercandies/Flutter_Candies/tree/master/gif/loading_moe_list/nested_scrollView.gif) |\n| ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |\n\n下面的代码展示怎么在CustomScrollView中构建加载更多列表\n\n```dart\n      LoadingMoreCustomScrollView(\n        slivers: \u003cWidget\u003e[\n          SliverAppBar(\n            pinned: true,\n            title: Text(\"MultipleSliverDemo\"),\n          ),\n          ///SliverList\n          LoadingMoreSliverList(SliverListConfig\u003cTuChongItem\u003e(\n            itemBuilder: ItemBuilder.itemBuilder,\n            sourceList: listSourceRepository,\n          )),\n          SliverToBoxAdapter(\n            child: Container(\n              alignment: Alignment.center,\n              child: Text(\"Next list\"),\n              color: Colors.blue,\n              height: 100.0,\n            ),\n          ),\n          ///SliverGrid\n          LoadingMoreSliverList(\n            SliverListConfig\u003cTuChongItem\u003e(\n              itemBuilder: ItemBuilder.itemBuilder,\n              sourceList: listSourceRepository1,\n              gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(\n                crossAxisCount: 2,\n                crossAxisSpacing: 3.0,\n                mainAxisSpacing: 3.0,\n              ),\n            ),\n          ),\n          SliverPersistentHeader(\n            delegate: CommonExtentSliverPersistentHeaderDelegate(\n                Container(\n                  alignment: Alignment.center,\n                  child: Text(\"Pinned Content\"),\n                  color: Colors.red,\n                ),\n                100.0),\n            pinned: true,\n          ),\n          ///SliverWaterfallFlow\n          LoadingMoreSliverList(\n            SliverListConfig\u003cTuChongItem\u003e(\n              itemBuilder: buildWaterfallFlowItem,\n              sourceList: listSourceRepository2,\n              padding: EdgeInsets.symmetric(horizontal: 5.0),\n              extendedListDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(\n                crossAxisCount: 2,\n                crossAxisSpacing: 5,\n                mainAxisSpacing: 5,\n              ),\n            ),\n          ),\n        ],\n      ),\n```\n\n## 状态效果\n\n| ![](https://github.com/fluttercandies/Flutter_Candies/tree/master/gif/loading_moe_list/error.gif) | ![](https://github.com/fluttercandies/Flutter_Candies/tree/master/gif/loading_moe_list/custom_indicator.gif) |\n| ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |\n\n为各种状态定义展示效果.\n\n``` dart\n        enum IndicatorStatus {\n          None,\n          LoadingMoreBusying,\n          FullScreenBusying,\n          Error,\n          FullScreenError,\n          NoMoreLoad,\n          Empty\n        }\n```\n``` dart\n      LoadingMoreList(\n        ListConfig\u003cTuChongItem\u003e(\n          itemBuilder: ItemBuilder.itemBuilder,\n          sourceList: listSourceRepository,\n          indicatorBuilder: _buildIndicator,\n          padding: EdgeInsets.all(0.0),\n        ),\n      ),\n\n  //you can use IndicatorWidget or build yourself widget\n  //in this demo, we define all status.\n  Widget _buildIndicator(BuildContext context, IndicatorStatus status) {\n    //if your list is sliver list ,you should build sliver indicator for it\n    //isSliver=true, when use it in sliver list\n    bool isSliver = false;\n\n    Widget widget;\n    switch (status) {\n      case IndicatorStatus.None:\n        widget = Container(height: 0.0);\n        break;\n      case IndicatorStatus.LoadingMoreBusying:\n        widget = Row(\n          mainAxisAlignment: MainAxisAlignment.center,\n          crossAxisAlignment: CrossAxisAlignment.center,\n          children: \u003cWidget\u003e[\n            Container(\n              margin: EdgeInsets.only(right: 5.0),\n              height: 15.0,\n              width: 15.0,\n              child: getIndicator(context),\n            ),\n            Text(\"正在加载...不要着急\")\n          ],\n        );\n        widget = _setbackground(false, widget, 35.0);\n        break;\n      case IndicatorStatus.FullScreenBusying:\n        widget = Row(\n          mainAxisAlignment: MainAxisAlignment.center,\n          crossAxisAlignment: CrossAxisAlignment.center,\n          children: \u003cWidget\u003e[\n            Container(\n              margin: EdgeInsets.only(right: 0.0),\n              height: 30.0,\n              width: 30.0,\n              child: getIndicator(context),\n            ),\n            Text(\"正在加载...不要着急\")\n          ],\n        );\n        widget = _setbackground(true, widget, double.infinity);\n        if (isSliver) {\n          widget = SliverFillRemaining(\n            child: widget,\n          );\n        } else {\n          widget = CustomScrollView(\n            slivers: \u003cWidget\u003e[\n              SliverFillRemaining(\n                child: widget,\n              )\n            ],\n          );\n        }\n        break;\n      case IndicatorStatus.Error:\n        widget = Text(\n          \"好像出现了问题呢？\",\n        );\n        widget = _setbackground(false, widget, 35.0);\n\n        widget = GestureDetector(\n          onTap: () {\n            listSourceRepository.errorRefresh();\n          },\n          child: widget,\n        );\n\n        break;\n      case IndicatorStatus.FullScreenError:\n        widget = Text(\n          \"好像出现了问题呢？\",\n        );\n        widget = _setbackground(true, widget, double.infinity);\n        widget = GestureDetector(\n          onTap: () {\n            listSourceRepository.errorRefresh();\n          },\n          child: widget,\n        );\n        if (isSliver) {\n          widget = SliverFillRemaining(\n            child: widget,\n          );\n        } else {\n          widget = CustomScrollView(\n            slivers: \u003cWidget\u003e[\n              SliverFillRemaining(\n                child: widget,\n              )\n            ],\n          );\n        }\n        break;\n      case IndicatorStatus.NoMoreLoad:\n        widget = Text(\"没有更多的了。。不要拖了\");\n        widget = _setbackground(false, widget, 35.0);\n        break;\n      case IndicatorStatus.Empty:\n        widget = EmptyWidget(\n          \"这里是空气！\",\n        );\n        widget = _setbackground(true, widget, double.infinity);\n        if (isSliver) {\n          widget = SliverToBoxAdapter(\n            child: widget,\n          );\n        } else {\n          widget = CustomScrollView(\n            slivers: \u003cWidget\u003e[\n              SliverFillRemaining(\n                child: widget,\n              )\n            ],\n          );\n        }\n        break;\n    }\n    return widget;\n  }\n\n```\n\n## 内存回收\n\n追踪列表元素回收，你可以在这个时刻回收一些内存，比如图片的内存缓存。\n\n[更多详情](https://github.com/fluttercandies/extended_image/blob/e1577bc4d0b57c725110a9d886703b98a72772b5/example/lib/pages/photo_view_demo.dart#L91)\n\n```dart\n        LoadingMoreList(\n          ListConfig\u003cTuChongItem\u003e(\n            extendedListDelegate: ExtendedListDelegate(\n              collectGarbage: (List\u003cint\u003e indexes) {\n                ///collectGarbage\n              },\n            )\n          ),\n        ),\n```\n\n## 可视区域追踪\n\n追踪进入Viewport的列表元素的index（即你看到的可视区域，并不包括缓存距离）\n\n```dart\n        LoadingMoreList(\n          ListConfig\u003cTuChongItem\u003e(\n            extendedListDelegate: ExtendedListDelegate(\n              viewportBuilder: (int firstIndex, int lastIndex) {\n                print('viewport : [$firstIndex,$lastIndex]');\n              },\n            ),\n          ),\n        ),\n```\n## LastChildLayoutType\n\n为最后一个元素创建特殊布局，这主要是用在将最后一个元素作为loadmore/no more的时候。\n\n```dart\n        enum LastChildLayoutType {\n        /// 普通的\n        none,\n\n        /// 将最后一个元素绘制在最大主轴Item之后，并且使用横轴大小最为layout size\n        /// 主要使用在[ExtendedGridView] and [WaterfallFlow]中，最后一个元素作为loadmore/no more元素的时候。\n        fullCrossAxisExtent,\n\n        /// 将最后一个child绘制在trailing of viewport，并且使用横轴大小最为layout size\n        /// 这种常用于最后一个元素作为loadmore/no more元素，并且列表元素没有充满整个viewport的时候\n        /// 如果列表元素充满viewport，那么效果跟fullCrossAxisExtent一样\n        foot,\n        }\n```\n\n## CloseToTrailing\n\n\n当reverse设置为true的时候，布局会变成如下。常用于聊天列表，新的会话会被插入0的位置，但是当会话没有充满viewport的时候，下面的布局不是我们想要的。\n\n```\n     trailing\n-----------------\n|               |\n|               |\n|     item2     |\n|     item1     |\n|     item0     |\n-----------------\n     leading\n```\n\n为了解决这个问题，你可以设置 closeToTrailing 为true, 布局将变成如下\n该属性同时支持[ExtendedGridView],[ExtendedList],[WaterfallFlow]。\n当然如果reverse如果不为ture，你设置这个属性依然会生效，没满viewport的时候布局会紧靠trailing\n\n```\n     trailing\n-----------------\n|     item2     |\n|     item1     |\n|     item0     |\n|               |\n|               |\n-----------------\n     leading\n```\n\n```dart\n      LoadingMoreList(\n        ListConfig\u003cTuChongItem\u003e(\n          extendedListDelegate: ExtendedListDelegate(\n            closeToTrailing: true\n          ),\n        ),\n      ),\n```\n## ☕️Buy me a coffee\n\n![img](http://zmtzawqlp.gitee.io/my_images/images/qrcode.png)\n","funding_links":["http://zmtzawqlp.gitee.io/my_images/images/qrcode.png"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffluttercandies%2Floading_more_list","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffluttercandies%2Floading_more_list","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffluttercandies%2Floading_more_list/lists"}