搜尋套件、儲存庫與 APP 分類

infinite_grouped_list 封面
套件詳情v2.0.0

infinite_grouped_list

Flutter 中的動態滾動清單,有效分組項目並在使用者滾動時無縫載入更多資料

AndroidiOSWebmacOSWindowsLinux
近 30 天下載
1980
喜歡數
60
Pub 分數
160

安裝套件

flutter pub add infinite_grouped_list

套件介紹

根據套件公開資料產生的選型評估,僅供參考。

一個 Flutter 套件,可實現動態、高效能的捲動清單,具備自動項目分組與無縫無限載入功能。它透過僅渲染可見項目,並在使用者捲動時智慧型取得額外資料來優化效能。非常適合需要結構化顯示且跨平台具有順暢使用者體驗的大數據集。

適用情境

  • 包含群組內容的大數據集
  • 即時訊息流滾動
  • 動態列表分頁
  • 具有惰性加載的離線優先應用
  • 內容密集型儀表板

主要特色

  • 自動項目分組
  • 無縫無限捲動
  • 高效記憶體使用
  • 跨平台支援
  • 可自訂的群組標題
  • 按需載入資料

適合對象

  • 開發可擴展列表介面的開發者
  • 包含大量資料集的應用程式
  • 需要響應式 UI 的專案
  • 針對多個平台的團隊
  • 需要優化效能的使用者

使用建議

  • 需要正確處理異步數據來源
  • 可能需要自定義邏輯來處理複雜的分組規則
  • 不適合靜態的小清單
  • 依賴於正確的狀態管理
  • 最佳搭配流或基於未來的資料提供者

原始 README

以下為關聯原始碼儲存庫的 README 原文快照,最新內容請造訪原始碼儲存庫。

Version Version

Show some love by dropping a ⭐ at GitHub
HTML tutorial

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.

  • Group Anchoring: Opt-in jump-to-group support lets you instantly scroll to any group (for example "Today") through the controller without impacting base performance.

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 pagination
  • page: Current page number for page-based pagination
  • limit: 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.

Jumping to a Group

Need to anchor the list to a specific group (e.g. "Today")? Enable anchoring on the widget and invoke the new controller helper:

final controller = InfiniteGroupedListController<Transaction, DateTime, String>();

InfiniteGroupedList(
  enableAnchoring: true,
  controller: controller,
  // ... other params
);

// Later, jump to a concrete title or resolve it dynamically with a predicate
// Option A: jump by the exact group title you already know
controller.jumpToGroup(
  title: 'Today',
  alignment: 0.0, // pin the header to the top
);

// Option B: resolve dynamically via predicate (provide predicate *instead* of title)
controller.jumpToGroup(
  predicate: (title, groupBy) => isSameDay(groupBy, DateTime.now()),
  alignment: 0.0,
  loadUntilFound: true, // imperative mode only
  maxRetries: 3,
);

Anchoring is opt-in, so you only incur the tiny bookkeeping cost when you actually need the feature. The optional loadUntilFound flag is available in imperative mode; reactive consumers should trigger their own data loads before retrying the jump. When loadUntilFound is enabled, maxRetries limits the extra page loads attempted and defaults to 3.

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.

  • 🎯 Jump to Group Example: Demonstrates enabling anchoring plus controller.jumpToGroup() to instantly scroll to the "Today" section.

  • 📅 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.

Git Hook

To block pushes when the package does not analyze or test cleanly, install the repo-local pre-push hook once:

./tool/install_git_hooks.sh

The hook runs:

  • fvm flutter analyze
  • fvm flutter test
Migration Guide

Version 1.4.0 note: The misspelled seperatorBuilder parameter was removed. Use separatorBuilder instead.

Existing users: If you were not using the misspelled separator parameter, your code continues to work without any further changes.

Moving to reactive pattern:

  1. Replace InfiniteGroupedList() with InfiniteGroupedList.reactive()
  2. Move your onLoadMore logic to your state management solution
  3. Replace the onLoadMore parameter with onLoadMoreTriggered callback
  4. Provide external state via items, isLoading, hasReachedMax parameters

The reactive pattern is recommended for new projects using modern state management, while the imperative pattern remains fully supported for simpler use cases.

所屬分類

依賴

依賴清單 2 項

原始碼儲存庫

使用此套件的專案

暫無相關資料。