flex_infinity_view 0.2.0 copy "flex_infinity_view: ^0.2.0" to clipboard
flex_infinity_view: ^0.2.0 copied to clipboard

Flexible infinite scrolling for Flutter lists, grids, and staggered layouts with loading, empty, and error states.

flex_infinity_view #

Flexible infinite scrolling for Flutter lists, grids, and simple staggered layouts with loading, empty, and error states built in.

Features #

  • Standalone and sliver-based infinite scrolling widgets
  • Support for ListView, GridView, and a two-column staggered layout
  • Vertical and horizontal infinite scrolling for list layouts
  • Automatic first-page loading and next-page loading on scroll
  • Explicit hasMore support so pagination can stop cleanly
  • Default initial loading with CircularProgressIndicator
  • Custom initial loading with loadingWidget
  • Custom widgets for loading, empty, error, and load-more states
  • External ScrollController support

Getting started #

Add the package to your pubspec.yaml:

dependencies:
  flex_infinity_view: ^0.2.0

Usage #

import 'package:flex_infinity_view/flex_infinity_view.dart';
import 'package:flutter/material.dart';

class ProductList extends StatefulWidget {
  const ProductList({super.key});

  @override
  State<ProductList> createState() => _ProductListState();
}

class _ProductListState extends State<ProductList> {
  final List<String> _items = [];

  bool _isLoading = false;
  bool _hasError = false;
  bool _hasMore = true;

  Future<void> _loadMore(int page, int limit) async {
    if (_isLoading) return;

    setState(() {
      _isLoading = true;
      _hasError = false;
    });

    try {
      await Future<void>.delayed(const Duration(milliseconds: 600));

      final nextItems = List.generate(
        limit,
        (index) => 'Item ${(page - 1) * limit + index + 1}',
      );

      setState(() {
        _items.addAll(nextItems);
        _hasMore = page < 4;
      });
    } catch (_) {
      setState(() => _hasError = true);
    } finally {
      setState(() => _isLoading = false);
    }
  }

  @override
  Widget build(BuildContext context) {
    return FlexInfinityView<String>(
      items: _items,
      limit: 8,
      isLoading: _isLoading,
      hasError: _hasError,
      hasMore: _hasMore,
      loadingWidget: const Center(child: CircularProgressIndicator()),
      onLoadMore: _loadMore,
      itemBuilder: (context, item, index) {
        return ListTile(title: Text(item));
      },
    );
  }
}

Layouts #

Use layoutType to switch between supported presentations:

FlexInfinityView<MyItem>(
  layoutType: InfiniteLayoutType.grid,
  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 2,
    childAspectRatio: 0.78,
  ),
  items: items,
  limit: 12,
  isLoading: isLoading,
  hasMore: hasMore,
  onLoadMore: fetchItems,
  itemBuilder: (context, item, index) => ProductCard(item: item),
)

Available values:

  • InfiniteLayoutType.list
  • InfiniteLayoutType.grid
  • InfiniteLayoutType.staggered

Horizontal lists #

Set scrollDirection to Axis.horizontal when using the list layout. Give the view a bounded height and each item a suitable width.

SizedBox(
  height: 240,
  child: FlexInfinityView<Product>(
    scrollDirection: Axis.horizontal,
    items: products,
    limit: 12,
    isLoading: isLoading,
    hasMore: hasMore,
    onLoadMore: fetchProducts,
    itemBuilder: (context, product, index) => SizedBox(
      width: 280,
      child: ProductCard(item: product),
    ),
  ),
)

Horizontal direction is supported only with InfiniteLayoutType.list. Vertical remains the default, so existing integrations keep their behavior.

Sliver usage #

Use FlexInfinitySliverView when you need to place the package inside an existing CustomScrollView.

CustomScrollView(
  slivers: [
    const SliverAppBar(
      pinned: true,
      title: Text('Products'),
    ),
    FlexInfinitySliverView<Product>(
      items: items,
      limit: 12,
      isLoading: isLoading,
      hasError: hasError,
      hasMore: hasMore,
      layoutType: InfiniteLayoutType.grid,
      gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 2,
        childAspectRatio: 0.78,
      ),
      onLoadMore: fetchProducts,
      itemBuilder: (context, item, index) => ProductCard(item: item),
    ),
  ],
)

A sliver follows its parent scroll axis. For a horizontal sliver list, set scrollDirection: Axis.horizontal on CustomScrollView and use InfiniteLayoutType.list on FlexInfinitySliverView.

SizedBox(
  height: 240,
  child: CustomScrollView(
    scrollDirection: Axis.horizontal,
    slivers: [
      FlexInfinitySliverView<Product>(
        layoutType: InfiniteLayoutType.list,
        items: products,
        limit: 12,
        isLoading: isLoading,
        hasMore: hasMore,
        onLoadMore: fetchProducts,
        itemBuilder: (context, product, index) => SizedBox(
          width: 400,
          child: ProductCard(item: product),
        ),
      ),
    ],
  ),
)

Do not set a separate direction on FlexInfinitySliverView: Flutter slivers inherit their main axis from the parent scroll view. As with standalone horizontal lists, give the viewport a bounded height and each item a finite width.

State handling #

The widget supports:

  • Initial loading with loadingWidget
  • Empty state with emptyWidget
  • Error state with errorWidget
  • Load-more state with loadMoreWidget
  • Pagination stop with hasMore

Example #

The example/ app demonstrates:

  • FlexInfinityView as a standalone scrollable
  • FlexInfinitySliverView inside CustomScrollView
  • Vertical and horizontal standalone lists
  • Vertical grid and horizontal list sliver composition
  • List, grid, and staggered layouts
  • Default loading and custom loading states
  • Empty responses
  • Initial request errors
  • Next-page request errors with retry

Run it with:

flutter run -d chrome example/lib/main.dart

Additional information #

Before publishing, run:

flutter analyze
flutter test
flutter pub publish --dry-run

Package page guidance used for this setup:

3
likes
160
points
123
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Flexible infinite scrolling for Flutter lists, grids, and staggered layouts with loading, empty, and error states.

Repository (GitHub)
View/report issues

Topics

#infinite-scroll #pagination #listview #gridview

License

MIT (license)

Dependencies

flutter

More

Packages that depend on flex_infinity_view