infinite_grouped_list 1.3.0
infinite_grouped_list: ^1.3.0 copied to clipboard
Dynamic scrolling list in Flutter, efficiently grouping items and seamlessly loading more data as user scrolls
Show some love by dropping a ⭐ at GitHub
Infinite Grouped List #
Brings together infinite scrolling, group-based item organization, and numerous other enhancements to improve the end-user experience.
Key Features #
-
Infinite Scrolling: The widget supports loading more data as the user reaches the end of the list. This is essential for handling large datasets without overwhelming the user or their device.
-
Grouping of Items: The widget can organize items into groups based on user-defined criteria. This helps to make sense of large amounts of data by breaking it down into manageable chunks.
-
Reactive State Management: 🆕 Full support for modern state management patterns like BLoC, Provider, and Riverpod with dedicated reactive constructors that separate event triggering from data listening.
-
Customizable Loading and Error States: You can provide custom widgets to be displayed while data is being loaded or if an error occurs. This allows for a seamless, branded experience.
-
Pull-to-Refresh: The widget incorporates a pull-to-refresh feature, letting users manually trigger a refresh of the list's content.
-
Sticky Group Headers: Headers stick to the top of the list as the user scrolls, making it easier to understand the context of the data they're viewing. Can be changed.
Usage #
The InfiniteGroupedList offers two usage patterns to fit different architectural approaches:
🔄 Reactive Pattern (Recommended for Modern Apps)
Perfect for apps using BLoC, Provider, Riverpod, or any external state management:
BlocBuilder<ItemsBloc, ItemsState>(
builder: (context, state) {
return InfiniteGroupedList<Item, String, String>.reactive(
// External state from your state management solution
items: state.items,
isLoading: state.isLoading,
hasReachedMax: state.hasReachedMax,
error: state.error,
// Event trigger - cleanly separated from data fetching
onLoadMoreTriggered: () {
context.read<ItemsBloc>().add(LoadMoreItems());
},
// Refresh trigger
onRefresh: () {
context.read<ItemsBloc>().add(RefreshItems());
},
// UI builders
itemBuilder: (item) => ListTile(title: Text(item.name)),
groupBy: (item) => item.category,
groupCreator: (category) => category,
groupTitleBuilder: (title, _, __, ___) => Text(title),
);
},
)
⚡ Imperative Pattern (Traditional Approach)
For apps that prefer direct data fetching within the widget:
InfiniteGroupedList(
onLoadMore: (paginationInfo) async {
// Fetch data directly and return it
return await apiService.fetchItems(
page: paginationInfo.page,
limit: 20,
);
},
itemBuilder: (item) => ListTile(title: Text(item.name)),
groupBy: (item) => item.category,
groupCreator: (category) => category,
groupTitleBuilder: (title, _, __, ___) => Text(title),
)
Key Differences
- Reactive: Event triggering and data listening are completely separated. Your state management handles data fetching, and the widget displays the current state.
- Imperative: The widget directly calls your data fetching function and manages the loading states internally.
PaginationInfo Helper
When using the imperative pattern, PaginationInfo provides pagination context:
offset: Current item offset for offset-based paginationpage: Current page number for page-based paginationlimit: Items per page (configurable via controller)
The InfiniteGroupedList widget is a comprehensive solution for any use case that involves displaying large amounts of data in an organized, easy-to-navigate manner.
Examples #
Explore comprehensive examples demonstrating different usage patterns:
-
🆕 Reactive BLoC Example: Complete implementation using reactive pattern with flutter_bloc, including error handling, loading states, and event-driven architecture.
-
📅 Group by Date: Traditional imperative pattern grouping transactions by date with custom group titles.
-
🏷️ Group by Type: Demonstrates grouping items by category/type with different visual treatments.
-
🔲 Grid Layout: Shows how to use the
.gridView()constructor for grid-based layouts.
Run the example app to see all patterns in action with an interactive example selection screen.
Migration Guide #
Existing users: Your current code continues to work without any changes! The new reactive constructors are purely additive.
Moving to reactive pattern:
- Replace
InfiniteGroupedList()withInfiniteGroupedList.reactive() - Move your
onLoadMorelogic to your state management solution - Replace the
onLoadMoreparameter withonLoadMoreTriggeredcallback - Provide external state via
items,isLoading,hasReachedMaxparameters
The reactive pattern is recommended for new projects using modern state management, while the imperative pattern remains fully supported for simpler use cases.
