import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import '../helpers/theme.dart'; import 'paginator_listener.dart'; typedef RowBuilder = Widget Function(dynamic); typedef OnScroll = void Function(bool down); typedef OnRemove = Function(dynamic t); class PaginatorListView extends StatefulWidget { final PaginatorListener paginatorListener; final RowBuilder rowBuilder; final OnScroll? onScroll; final ScrollController _scrollController; final Color color; final OnRemove? onRemove; final Widget? noMoreData; PaginatorListView( {Key? key, required this.paginatorListener, required this.rowBuilder, this.onScroll, this.color = Colors.blueAccent, this.noMoreData, this.onRemove}) : _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 State> createState() => _PaginatorListViewState(); } class _PaginatorListViewState extends State> { late PaginatorListener _paginatorListener; @override initState() { super.initState(); initListener(); } @override void didUpdateWidget(covariant PaginatorListView oldWidget) { super.didUpdateWidget(oldWidget); initListener(); } initListener() { _paginatorListener = widget.paginatorListener; widget.paginatorListener.addListener(() { if (mounted) { setState(() {}); } }); } @override Widget build(BuildContext context) { bool ended = _paginatorListener.ended; int count = _paginatorListener.data.length; if (ended) count++; return Column( children: [ Expanded( child: RefreshIndicator( color: primaryColor, onRefresh: () { return _paginatorListener.refresh(); }, child: ListView.separated( separatorBuilder: (context, index) => Divider(height: 1, color: dividerColor), controller: widget._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: widget.noMoreData ?? const Text("No more data")), ); } T t = _paginatorListener.data[index]; return widget.rowBuilder(t); }), ), ), _paginatorListener.isLoading ? _loadingRow() : Container() ], ); } Widget _loadingRow() { return Container( padding: const EdgeInsets.all(8), color: Colors.transparent, child: Row( mainAxisAlignment: MainAxisAlignment.center, children: [ Column( children: [ CircularProgressIndicator( valueColor: AlwaysStoppedAnimation(widget.color)), Text( "Loading...", style: TextStyle(color: widget.color), ) ], ), ], ), ); } }