my_refresh_list.dart
3.8 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:Parlando/res/resources.dart';
import 'package:Parlando/util/theme_utils.dart';
import 'package:Parlando/widgets/state_layout.dart';
/// 封装下拉刷新与加载更多
class DeerListView extends StatefulWidget {
const DeerListView({
Key? key,
required this.itemCount,
required this.itemBuilder,
required this.onRefresh,
this.loadMore,
this.hasMore = false,
this.stateType = StateType.empty,
this.pageSize = 10,
this.padding,
this.itemExtent,
}) : super(key: key);
final RefreshCallback onRefresh;
final LoadMoreCallback? loadMore;
final int itemCount;
final bool hasMore;
final IndexedWidgetBuilder itemBuilder;
final StateType stateType;
/// 一页的数量,默认为10
final int pageSize;
/// padding属性使用时注意会破坏原有的SafeArea,需要自行计算bottom大小
final EdgeInsetsGeometry? padding;
final double? itemExtent;
@override
_DeerListViewState createState() => _DeerListViewState();
}
typedef RefreshCallback = Future<void> Function();
typedef LoadMoreCallback = Future<void> Function();
class _DeerListViewState extends State<DeerListView> {
/// 是否正在加载数据
bool _isLoading = false;
@override
Widget build(BuildContext context) {
final Widget child = RefreshIndicator(
onRefresh: widget.onRefresh,
child: widget.itemCount == 0
? StateLayout(type: widget.stateType)
: ListView.builder(
itemCount: widget.loadMore == null
? widget.itemCount
: widget.itemCount + 1,
padding: widget.padding,
itemExtent: widget.itemExtent,
itemBuilder: (BuildContext context, int index) {
/// 不需要加载更多则不需要添加FootView
if (widget.loadMore == null) {
return widget.itemBuilder(context, index);
} else {
return index < widget.itemCount
? widget.itemBuilder(context, index)
: MoreWidget(
widget.itemCount, widget.hasMore, widget.pageSize);
}
},
),
);
return SafeArea(
child: NotificationListener<ScrollNotification>(
onNotification: (ScrollNotification note) {
/// 确保是垂直方向滚动,且滑动至底部
if (note.metrics.pixels == note.metrics.maxScrollExtent &&
note.metrics.axis == Axis.vertical) {
_loadMore();
}
return true;
},
child: child,
),
);
}
Future<void> _loadMore() async {
if (widget.loadMore == null) {
return;
}
if (_isLoading) {
return;
}
if (!widget.hasMore) {
return;
}
_isLoading = true;
await widget.loadMore?.call();
_isLoading = false;
}
}
class MoreWidget extends StatelessWidget {
const MoreWidget(this.itemCount, this.hasMore, this.pageSize, {Key? key})
: super(key: key);
final int itemCount;
final bool hasMore;
final int pageSize;
@override
Widget build(BuildContext context) {
final TextStyle style = context.isDark
? TextStyles.textGray14
: const TextStyle(color: Color(0x8A000000));
return Padding(
padding: const EdgeInsets.symmetric(vertical: 10.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
if (hasMore) const CupertinoActivityIndicator(),
if (hasMore) Gaps.hGap5,
/// 只有一页的时候,就不显示FooterView了
Text(hasMore ? '正在加载中...' : (itemCount < pageSize ? '' : '没有了呦~'),
style: style),
],
),
);
}
}