feat(flutter): 增加榜单新剧分页与预约刷新
This commit is contained in:
1 parent
805762f761
commit
c4dcb714ab
12 files changed
+611
-96
No files matched your search
@@ -0,0 +1,116 @@
|
||||
// Author: fruit.com.cn
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import '../theme/app_colors.dart';
|
||||
|
||||
const int _defaultPageSize = 20;
|
||||
const Duration _defaultLoadDelay = Duration(milliseconds: 300);
|
||||
|
||||
/// 客户端本地列表分页状态。
|
||||
class PagedLocalListController<T> extends ChangeNotifier {
|
||||
PagedLocalListController({
|
||||
List<T> items = const [],
|
||||
this.pageSize = _defaultPageSize,
|
||||
this.minimumLoadDelay = _defaultLoadDelay,
|
||||
}) : _items = List<T>.unmodifiable(items);
|
||||
|
||||
final int pageSize;
|
||||
final Duration minimumLoadDelay;
|
||||
|
||||
List<T> _items;
|
||||
int _pageCount = 1;
|
||||
int _generation = 0;
|
||||
bool _loading = false;
|
||||
bool _disposed = false;
|
||||
|
||||
List<T> get items => _items;
|
||||
bool get loading => _loading;
|
||||
bool get hasMore => visibleItems.length < _items.length;
|
||||
|
||||
List<T> get visibleItems =>
|
||||
_items.take(_pageCount * pageSize).toList(growable: false);
|
||||
|
||||
/// 用最新目录替换本地数据,并回到第一页。
|
||||
void replaceAll(List<T> items) {
|
||||
_generation++;
|
||||
_items = List<T>.unmodifiable(items);
|
||||
_pageCount = 1;
|
||||
_loading = false;
|
||||
_notify();
|
||||
}
|
||||
|
||||
/// 追加下一页;已加载完或正在加载时不重复触发。
|
||||
Future<void> loadMore() async {
|
||||
if (_loading || !hasMore) return;
|
||||
final generation = _generation;
|
||||
_loading = true;
|
||||
_notify();
|
||||
await Future<void>.delayed(minimumLoadDelay);
|
||||
if (_disposed || generation != _generation) return;
|
||||
_pageCount++;
|
||||
_loading = false;
|
||||
_notify();
|
||||
}
|
||||
|
||||
void _notify() {
|
||||
if (!_disposed) notifyListeners();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_disposed = true;
|
||||
super.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
/// 分页列表底部加载态与到底提示。
|
||||
class PagedLoadFooter extends StatelessWidget {
|
||||
const PagedLoadFooter({
|
||||
super.key,
|
||||
required this.loading,
|
||||
required this.hasMore,
|
||||
required this.hasItems,
|
||||
required this.loadMoreKey,
|
||||
required this.noMoreKey,
|
||||
required this.noMoreLabel,
|
||||
});
|
||||
|
||||
final bool loading;
|
||||
final bool hasMore;
|
||||
final bool hasItems;
|
||||
final Key loadMoreKey;
|
||||
final Key noMoreKey;
|
||||
final String noMoreLabel;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
if (loading) {
|
||||
return SizedBox(
|
||||
key: loadMoreKey,
|
||||
height: 56,
|
||||
child: const Center(
|
||||
child: SizedBox.square(
|
||||
dimension: 20,
|
||||
child: CircularProgressIndicator(
|
||||
strokeWidth: 2,
|
||||
color: AppColors.blue,
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
if (hasItems && !hasMore) {
|
||||
return Padding(
|
||||
key: noMoreKey,
|
||||
padding: const EdgeInsets.symmetric(vertical: 14),
|
||||
child: Text(
|
||||
noMoreLabel,
|
||||
textAlign: TextAlign.center,
|
||||
style: const TextStyle(color: AppColors.muted, fontSize: 12),
|
||||
),
|
||||
);
|
||||
}
|
||||
return const SizedBox(height: 16);
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user