import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:liftmanager/res/resources.dart'; import 'package:liftmanager/utils/theme_utils.dart'; import 'package:liftmanager/widgets/state_layout.dart'; /// 封装下拉刷新与加载更多 class ChatListView extends StatefulWidget { const ChatListView({ Key key, @required this.itemCount, @required this.itemBuilder, @required this.onRefresh, this.loadMore, this.hasMore: false, this.pageSize: 10, this.padding, this.itemExtent, this.scrollController, }) : super(key: key); final RefreshCallback onRefresh; final LoadMoreCallback loadMore; final int itemCount; final bool hasMore; final IndexedWidgetBuilder itemBuilder; /// 一页的数量,默认为10 final int pageSize; final EdgeInsetsGeometry padding; final double itemExtent; final ScrollController scrollController; @override _ChatListViewState createState() => _ChatListViewState(); } typedef RefreshCallback = Future Function(); typedef LoadMoreCallback = Future Function(); class _ChatListViewState extends State { /// 是否正在加载数据 bool _isLoading = false; @override Widget build(BuildContext context) { return SafeArea( child: NotificationListener( onNotification: (ScrollNotification note) { /// 确保是垂直方向滚动,且滑动至顶部 // if (note.metrics.pixels == note.metrics.maxScrollExtent && note.metrics.axis == Axis.vertical){ if (note.metrics.pixels == 0.0 && note.metrics.axis == Axis.vertical && note.metrics.maxScrollExtent != 0.0 && note.metrics.extentBefore == 0.0) { print("到顶了。。。"); } ScrollMetrics metrics = note.metrics; // print(metrics.pixels);// 当前位置 // print(metrics.atEdge);//是否在顶部或底部 // print(metrics.axis);//垂直或水平滚动 // print(metrics.axisDirection);// 滚动方向是down还是up // print(metrics.extentAfter);//视口底部距离列表底部有多大 // print(metrics.extentBefore);//视口顶部距离列表顶部有多大 // print(metrics.extentInside);//视口范围内的列表长度 // print(metrics.maxScrollExtent);//最大滚动距离,列表长度-视口长度 // print(metrics.minScrollExtent);//最小滚动距离 // print(metrics.viewportDimension);//视口长度 // print(metrics.outOfRange);//是否越过边界 // print('------------------------'); return true; }, child: RefreshIndicator( displacement: 1.0, onRefresh: widget.onRefresh, child: ListView.builder( // shrinkWrap: true, itemCount: widget.itemCount, controller: widget.scrollController, reverse: false, physics: new AlwaysScrollableScrollPhysics(), padding: widget.padding, itemExtent: widget.itemExtent, itemBuilder: (BuildContext context, int index) { return widget.itemBuilder(context, index); }), ), ), ); } Future _loadMore() async { if (widget.loadMore == null) { return; } if (_isLoading) { return; } if (!widget.hasMore) { return; } _isLoading = true; await widget.loadMore(); _isLoading = false; } } class MoreWidget extends StatelessWidget { const MoreWidget(this.itemCount, this.hasMore, this.pageSize); final int itemCount; final bool hasMore; final int pageSize; @override Widget build(BuildContext context) { final style = const TextStyle(color: Color(0xff666666)); return Container( color: ThemeUtils.getTabsBg(context), child: Padding( padding: EdgeInsets.only(top: 10, bottom: 30), child: Row( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ hasMore ? const CupertinoActivityIndicator() : Gaps.empty, hasMore ? Gaps.hGap5 : Gaps.empty, /// 只有一页的时候,就不显示FooterView了 Text(hasMore ? '正在加载中...' : (itemCount < pageSize ? '' : '没有了呦~'), style: style), ], ), ), ); } }