Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/fluttercandies/loading_more_list
A loading more list which supports ListView,GridView,WaterfallFlow and Slivers.
https://github.com/fluttercandies/loading_more_list
flutter load-more pull-up-refresh sliverlist waterfall-flow
Last synced: 4 days ago
JSON representation
A loading more list which supports ListView,GridView,WaterfallFlow and Slivers.
- Host: GitHub
- URL: https://github.com/fluttercandies/loading_more_list
- Owner: fluttercandies
- License: mit
- Created: 2019-02-14T15:26:44.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2024-09-14T10:02:59.000Z (2 months ago)
- Last Synced: 2024-09-14T20:39:32.828Z (2 months ago)
- Topics: flutter, load-more, pull-up-refresh, sliverlist, waterfall-flow
- Language: Dart
- Homepage:
- Size: 3.77 MB
- Stars: 357
- Watchers: 6
- Forks: 45
- Open Issues: 3
-
Metadata Files:
- Readme: README-ZH.md
- Changelog: CHANGELOG.md
- Funding: .github/FUNDING.yml
- License: LICENSE
- Codeowners: CODEOWNERS
Awesome Lists containing this project
README
# loading_more_list
加载更多列表支持ListView,GridView以及瀑布流。
[![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)
[掘金社区文章](https://juejin.im/post/5bfb9cb7e51d45592b766769)
语言: [English](README.md) | 中文简体
[Web demo for LoadingMoreList](https://fluttercandies.github.io/loading_more_list/)
- [loading_more_list](#loading_more_list)
- [使用](#使用)
- [准备数据源](#准备数据源)
- [参数](#参数)
- [Widget](#widget)
- [ListView](#listview)
- [GridView](#gridview)
- [瀑布流](#瀑布流)
- [Sliver/CustomScrollView](#slivercustomscrollview)
- [状态效果](#状态效果)
- [内存回收](#内存回收)
- [可视区域追踪](#可视区域追踪)
- [LastChildLayoutType](#lastchildlayouttype)
- [CloseToTrailing](#closetotrailing)
- [☕️Buy me a coffee](#️buy-me-a-coffee)## 使用
* 添加库到 pubspec.yaml
```yaml
dependencies:
loading_more_list: any```
* 导入库```dart
import 'package:loading_more_list/loading_more_list.dart';
```
## 准备数据源
你需要继承LoadingMoreBase来实现加载更多的数据源. 通过重写loadData方法来加载数据. 当没有数据的时候记得把hasMore设置为false.
```dart
class TuChongRepository extends LoadingMoreBase {
int pageindex = 1;
bool _hasMore = true;
bool forceRefresh = false;
@override
bool get hasMore => (_hasMore && length < 30) || forceRefresh;@override
Future refresh([bool clearBeforeRequest = false]) async {
_hasMore = true;
pageindex = 1;
//force to refresh list when you don't want clear list before request
//for the case, if your list already has 20 items.
forceRefresh = !clearBeforeRequest;
var result = await super.refresh(clearBeforeRequest);
forceRefresh = false;
return result;
}@override
Future loadData([bool isloadMoreAction = false]) async {
String url = "";
if (this.length == 0) {
url = "https://api.tuchong.com/feed-app";
} else {
int lastPostId = this[this.length - 1].postId;
url =
"https://api.tuchong.com/feed-app?post_id=$lastPostId&page=$pageindex&type=loadmore";
}
bool isSuccess = false;
try {
//to show loading more clearly, in your app,remove this
await Future.delayed(Duration(milliseconds: 500));var result = await HttpClientHelper.get(url);
var source = TuChongSource.fromJson(json.decode(result.body));
if (pageindex == 1) {
this.clear();
}
for (var item in source.feedList) {
if (item.hasImage && !this.contains(item) && hasMore) this.add(item);
}_hasMore = source.feedList.length != 0;
pageindex++;
isSuccess = true;
} catch (exception, stack) {
isSuccess = false;
print(exception);
print(stack);
}
return isSuccess;
}
}```
## 参数
大部分参数都跟官方列表一样.
下面的参数是为加载更多而设计的.
ListConfig 和 SliverListConfig
| 参数 | 描述 | 默认 |
| -------------------- | --------------------------------------------- | ------------------------ |
| itemBuilder | 列表元素构建器. | 必填 |
| sourceList | 数据源继承于LoadingMoreBase. | 必填 |
| showGlowLeading | 是否显示过度拖拽上部波纹. | 0.0 |
| showGlowTrailing | 是否显示过度拖拽下部波纹. | - |
| lastChildLayoutType | 最后一个元素的布局样式(loadmore/no more元素). | LastChildLayoutType.foot |
| extendedListDelegate | WaterfallFlow 或者 ExtendedList的委托 | - |
| gridDelegate | GridView定义委托. | - |
| indicatorBuilder | 状态指示构建器. | IndicatorWidget |
| padding | 边距,SliverListConfig的参数 | - |
| childCountBuilder | 动态获取 child count的回调,入参为列表的长度 | - |## Widget
LoadingMoreList
| 参数 | 描述 | 默认 |
| -------------------- | ---------------------- | -------- |
| listConfig | ListConfig 构建参数 | required |
| onScrollNotification | 获取滚动冒泡通知. | - |LoadingMoreSliverList
| 参数 | 描述 | 默认 |
| ---------------- | ---------------------------- | -------- |
| sliverListConfig | SliverListConfig 构建参数 | required |LoadingMoreCustomScrollView
| 参数 | 描述 | 默认 |
| ----------------------- | ------------------------------------------------------------------------- | ----- |
| onScrollNotification | 获取滚动冒泡通知. | - |## ListView
![](https://github.com/fluttercandies/Flutter_Candies/tree/master/gif/loading_moe_list/listview.gif)
```dart
LoadingMoreList(
ListConfig(
itemBuilder: ItemBuilder.itemBuilder,
sourceList: listSourceRepository,
padding: EdgeInsets.all(0.0),
),
),
```## GridView
通过gridDelegate定义GridView
```dart
LoadingMoreList(
ListConfig(
itemBuilder: ItemBuilder.itemBuilder,
sourceList: listSourceRepository,
padding: EdgeInsets.all(0.0),
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 3.0,
mainAxisSpacing: 3.0,
),
),
),
```## 瀑布流
![](https://github.com/fluttercandies/Flutter_Candies/tree/master/gif/waterfall_flow/known_sized.gif)
通过waterfallFlowDelegate定义瀑布流
```dart
LoadingMoreList(
ListConfig(
extendedListDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 5,
mainAxisSpacing: 5,
),
itemBuilder: _buildItem,
sourceList: listSourceRepository,
padding: EdgeInsets.all(5.0),
),
),
```## Sliver/CustomScrollView
| ![](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) |
| ----------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- |下面的代码展示怎么在CustomScrollView中构建加载更多列表
```dart
LoadingMoreCustomScrollView(
slivers: [
SliverAppBar(
pinned: true,
title: Text("MultipleSliverDemo"),
),
///SliverList
LoadingMoreSliverList(SliverListConfig(
itemBuilder: ItemBuilder.itemBuilder,
sourceList: listSourceRepository,
)),
SliverToBoxAdapter(
child: Container(
alignment: Alignment.center,
child: Text("Next list"),
color: Colors.blue,
height: 100.0,
),
),
///SliverGrid
LoadingMoreSliverList(
SliverListConfig(
itemBuilder: ItemBuilder.itemBuilder,
sourceList: listSourceRepository1,
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 3.0,
mainAxisSpacing: 3.0,
),
),
),
SliverPersistentHeader(
delegate: CommonExtentSliverPersistentHeaderDelegate(
Container(
alignment: Alignment.center,
child: Text("Pinned Content"),
color: Colors.red,
),
100.0),
pinned: true,
),
///SliverWaterfallFlow
LoadingMoreSliverList(
SliverListConfig(
itemBuilder: buildWaterfallFlowItem,
sourceList: listSourceRepository2,
padding: EdgeInsets.symmetric(horizontal: 5.0),
extendedListDelegate: SliverWaterfallFlowDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 5,
mainAxisSpacing: 5,
),
),
),
],
),
```## 状态效果
| ![](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) |
| ------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |为各种状态定义展示效果.
``` dart
enum IndicatorStatus {
None,
LoadingMoreBusying,
FullScreenBusying,
Error,
FullScreenError,
NoMoreLoad,
Empty
}
```
``` dart
LoadingMoreList(
ListConfig(
itemBuilder: ItemBuilder.itemBuilder,
sourceList: listSourceRepository,
indicatorBuilder: _buildIndicator,
padding: EdgeInsets.all(0.0),
),
),//you can use IndicatorWidget or build yourself widget
//in this demo, we define all status.
Widget _buildIndicator(BuildContext context, IndicatorStatus status) {
//if your list is sliver list ,you should build sliver indicator for it
//isSliver=true, when use it in sliver list
bool isSliver = false;Widget widget;
switch (status) {
case IndicatorStatus.None:
widget = Container(height: 0.0);
break;
case IndicatorStatus.LoadingMoreBusying:
widget = Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
margin: EdgeInsets.only(right: 5.0),
height: 15.0,
width: 15.0,
child: getIndicator(context),
),
Text("正在加载...不要着急")
],
);
widget = _setbackground(false, widget, 35.0);
break;
case IndicatorStatus.FullScreenBusying:
widget = Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Container(
margin: EdgeInsets.only(right: 0.0),
height: 30.0,
width: 30.0,
child: getIndicator(context),
),
Text("正在加载...不要着急")
],
);
widget = _setbackground(true, widget, double.infinity);
if (isSliver) {
widget = SliverFillRemaining(
child: widget,
);
} else {
widget = CustomScrollView(
slivers: [
SliverFillRemaining(
child: widget,
)
],
);
}
break;
case IndicatorStatus.Error:
widget = Text(
"好像出现了问题呢?",
);
widget = _setbackground(false, widget, 35.0);widget = GestureDetector(
onTap: () {
listSourceRepository.errorRefresh();
},
child: widget,
);break;
case IndicatorStatus.FullScreenError:
widget = Text(
"好像出现了问题呢?",
);
widget = _setbackground(true, widget, double.infinity);
widget = GestureDetector(
onTap: () {
listSourceRepository.errorRefresh();
},
child: widget,
);
if (isSliver) {
widget = SliverFillRemaining(
child: widget,
);
} else {
widget = CustomScrollView(
slivers: [
SliverFillRemaining(
child: widget,
)
],
);
}
break;
case IndicatorStatus.NoMoreLoad:
widget = Text("没有更多的了。。不要拖了");
widget = _setbackground(false, widget, 35.0);
break;
case IndicatorStatus.Empty:
widget = EmptyWidget(
"这里是空气!",
);
widget = _setbackground(true, widget, double.infinity);
if (isSliver) {
widget = SliverToBoxAdapter(
child: widget,
);
} else {
widget = CustomScrollView(
slivers: [
SliverFillRemaining(
child: widget,
)
],
);
}
break;
}
return widget;
}```
## 内存回收
追踪列表元素回收,你可以在这个时刻回收一些内存,比如图片的内存缓存。
[更多详情](https://github.com/fluttercandies/extended_image/blob/e1577bc4d0b57c725110a9d886703b98a72772b5/example/lib/pages/photo_view_demo.dart#L91)
```dart
LoadingMoreList(
ListConfig(
extendedListDelegate: ExtendedListDelegate(
collectGarbage: (List indexes) {
///collectGarbage
},
)
),
),
```## 可视区域追踪
追踪进入Viewport的列表元素的index(即你看到的可视区域,并不包括缓存距离)
```dart
LoadingMoreList(
ListConfig(
extendedListDelegate: ExtendedListDelegate(
viewportBuilder: (int firstIndex, int lastIndex) {
print('viewport : [$firstIndex,$lastIndex]');
},
),
),
),
```
## LastChildLayoutType为最后一个元素创建特殊布局,这主要是用在将最后一个元素作为loadmore/no more的时候。
```dart
enum LastChildLayoutType {
/// 普通的
none,/// 将最后一个元素绘制在最大主轴Item之后,并且使用横轴大小最为layout size
/// 主要使用在[ExtendedGridView] and [WaterfallFlow]中,最后一个元素作为loadmore/no more元素的时候。
fullCrossAxisExtent,/// 将最后一个child绘制在trailing of viewport,并且使用横轴大小最为layout size
/// 这种常用于最后一个元素作为loadmore/no more元素,并且列表元素没有充满整个viewport的时候
/// 如果列表元素充满viewport,那么效果跟fullCrossAxisExtent一样
foot,
}
```## CloseToTrailing
当reverse设置为true的时候,布局会变成如下。常用于聊天列表,新的会话会被插入0的位置,但是当会话没有充满viewport的时候,下面的布局不是我们想要的。
```
trailing
-----------------
| |
| |
| item2 |
| item1 |
| item0 |
-----------------
leading
```为了解决这个问题,你可以设置 closeToTrailing 为true, 布局将变成如下
该属性同时支持[ExtendedGridView],[ExtendedList],[WaterfallFlow]。
当然如果reverse如果不为ture,你设置这个属性依然会生效,没满viewport的时候布局会紧靠trailing```
trailing
-----------------
| item2 |
| item1 |
| item0 |
| |
| |
-----------------
leading
``````dart
LoadingMoreList(
ListConfig(
extendedListDelegate: ExtendedListDelegate(
closeToTrailing: true
),
),
),
```
## ☕️Buy me a coffee![img](http://zmtzawqlp.gitee.io/my_images/images/qrcode.png)