import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'paginator_listener.dart'; typedef RowBuilder = Widget Function(dynamic); typedef OnScroll = void Function(bool down); class PaginatorListView extends StatelessWidget { final PaginatorListener paginatorListener; final RowBuilder rowBuilder; final OnScroll? onScroll; final ScrollController _scrollController; final Color color; PaginatorListView( {Key? key, required this.paginatorListener, required this.rowBuilder, this.onScroll, this.color = Colors.blueAccent}) : _scrollController = ScrollController(), super(key: key) { _scrollController.addListener(() async { if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { paginatorListener.loadMore(); } if (onScroll != null) { var down = _scrollController.position.userScrollDirection == ScrollDirection.forward; onScroll!(down); } }); } @override Widget build(BuildContext context) { bool ended = paginatorListener.ended; int count = paginatorListener.data.length; if (ended) count++; return Column( children: [ Expanded( child: RefreshIndicator( onRefresh: () { return paginatorListener.refresh(); }, child: ListView.separated( separatorBuilder: (context, index) => Divider(height: 1, color: Colors.black), controller: _scrollController, scrollDirection: Axis.vertical, physics: const AlwaysScrollableScrollPhysics(), shrinkWrap: true, itemCount: count, itemBuilder: (BuildContext context, int index) { if (ended && index == count - 1) { return Padding( padding: const EdgeInsets.all(8.0), child: Center(child: Text("No more data")), ); } T t = paginatorListener.data[index]; return rowBuilder(t); }), ), ), paginatorListener.isLoading ? _loadingRow() : Container() ], ); } Widget _loadingRow() { return Container( padding: EdgeInsets.all(8), color: Colors.transparent, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Column( children: [ CircularProgressIndicator( valueColor: new AlwaysStoppedAnimation(color)), Text( "Loading...", style: TextStyle(color: color), ) ], ), ], ), ); } }