my_refresh_list.dart 4.3 KB

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