An open API service indexing awesome lists of open source software.

https://github.com/dariomatias-dev/scroll_infinity

Add infinite scrolling to your Flutter lists quickly and easily, with simple and fast implementation.
https://github.com/dariomatias-dev/scroll_infinity

dart dartlang flutter flutter-package mit mit-license package pubdev

Last synced: 22 days ago
JSON representation

Add infinite scrolling to your Flutter lists quickly and easily, with simple and fast implementation.

Awesome Lists containing this project

README

          




Flutter
Dart


Scroll Infinity


A Flutter widget that provides an infinite scrollable list with built-in support for paginated data loading, state handling, and flexible customization.


Explore the docs »



View on pub.dev
·
Report Bug
·
Request Feature






## Table of Contents

- [About The Project](#about-the-project)
- [Features](#features)
- [Built With](#built-with)
- [Getting Started](#getting-started)
- [Usage](#usage)
- [Basic Vertical Scroll](#basic-vertical-scroll)
- [Basic Horizontal Scroll](#basic-horizontal-scroll)
- [Vertical Scroll with Interval](#vertical-scroll-with-interval)
- [Properties](#properties)
- [Contributing](#contributing)
- [License](#license)
- [Author](#author)

## About The Project

ScrollInfinity simplifies implementing infinite scroll lists in Flutter. It handles paginated loading, state management (loading, empty, error), and user interactions, letting developers focus on building item UIs.

It offers customization for manual/automatic loading, custom state widgets, and both vertical and horizontal layouts.

### Development Environment

| Tool | Version Used |
| ----------- | ------------ |
| Flutter SDK | 3.32.7 |
| Dart SDK | 3.8.1 |

## Features

- Infinite scroll with pagination
- Manual or automatic data loading
- Custom "Load More" and "Try Again" builders
- Loading, error, and empty states handling
- Optional scrollbars, header widget, and separators
- Vertical and horizontal scrolling support
- Initial items support
- Insert null values at intervals (ads/dividers)
- Retry attempts limit on error
- Real item index mapping with intervals

## Built With

- **[Flutter](https://flutter.dev/)** – A UI toolkit by Google for building beautiful, natively compiled applications for mobile, web, and desktop from a single codebase.
- **[Dart](https://dart.dev/)** – The programming language used for Flutter, optimized for building fast apps on any platform.

## Getting Started

Install:

```bash
flutter pub add scroll_infinity
```

## Usage

Pagination requests a new page when the user reaches the list end.
If `loadData` returns `null`, the error state is shown.

**Note:** Use a nullable type `T?` when using `interval`, as null values are inserted.

### Basic Vertical Scroll

```dart

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

void main() {
runApp(
const MaterialApp(
debugShowCheckedModeBanner: false,
home: MyApp(),
),
);
}

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

@override
State createState() => _MyAppState();
}

class _MyAppState extends State {
static const _maxItems = 20;

@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: ScrollInfinity(
maxItems: _maxItems,
loadData: (page) async {
await Future.delayed(const Duration(seconds: 2));

return List.generate(
_maxItems,
(index) => page * _maxItems + index + 1,
);
},
itemBuilder: (value, index) {
return ListTile(
title: Text('Item $value'),
subtitle: Text('Subtitle $value'),
);
},
),
),
);
}
}
```

### Basic Horizontal Scroll

```dart

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

void main() {
runApp(
const MaterialApp(
debugShowCheckedModeBanner: false,
home: MyApp(),
),
);
}

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

@override
State createState() => _MyAppState();
}

class _MyAppState extends State {
static const _maxItems = 10;

@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
height: 100.0,
child: ScrollInfinity(
scrollDirection: Axis.horizontal,
maxItems: _maxItems,
loadData: (page) async {
await Future.delayed(const Duration(seconds: 2));

return List.generate(
_maxItems,
(index) => page * _maxItems + index + 1,
);
},
itemBuilder: (value, index) {
return Center(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Text('Item $value'),
),
);
},
),
),
),
);
}
}
```

### Vertical Scroll with Interval

```dart

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

void main() {
runApp(
const MaterialApp(
debugShowCheckedModeBanner: false,
home: MyApp(),
),
);
}

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

@override
State createState() => _MyAppState();
}

class _MyAppState extends State {
static const _maxItems = 20;

@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: ScrollInfinity(
maxItems: _maxItems,
interval: 2,
loadData: (page) async {
await Future.delayed(const Duration(seconds: 2));

return List.generate(
_maxItems,
(index) => page * _maxItems + index + 1,
);
},
itemBuilder: (value, index) {
if (value == null) return const Divider();

return ListTile(
title: Text('Item $value'),
);
},
),
),
);
}
}
```

## Properties

**Core Data Handling**

| Name | Type | Default | Description |
| ---------------- | ------------------------------------- | ------- | ------------------------ |
| loadData | `Future?> Function(int)` | – | Fetch data for each page |
| itemBuilder | `Widget Function(T value, int index)` | – | Builds each item |
| maxItems | `int` | – | Max items per request |
| initialItems | `List?` | null | Items before first fetch |
| initialPageIndex | `int` | 0 | Starting page index |

**Layout & Appearance**

| Name | Type | Default | Description |
| ---------------- | ------------------------------------- | -------- | ---------------- |
| scrollDirection | `Axis` | vertical | Scroll direction |
| padding | `EdgeInsetsGeometry?` | null | Internal padding |
| header | `Widget?` | null | Header widget |
| separatorBuilder | `Widget Function(BuildContext, int)?` | null | Separators |
| scrollbars | `bool` | true | Show scrollbars |

**Behavioral Features**

| Name | Type | Default | Description |
| ---------------- | ------ | ------- | ---------------------------- |
| interval | `int?` | null | Null item insertion interval |
| useRealItemIndex | `bool` | true | Independent indexing |
| automaticLoading | `bool` | true | Auto-fetch on scroll |

**Error Handling**

| Name | Type | Default | Description |
| ------------------ | ------ | ------- | ----------- |
| enableRetryOnError | `bool` | true | Allow retry |
| maxRetries | `int?` | null | Retry limit |

**State-Specific Widgets**

| Name | Type | Default | Description |
| ----------------- | -------------------------------- | ------- | -------------------------- |
| loading | `Widget?` | null | Loading state widget |
| empty | `Widget?` | null | Empty state widget |
| tryAgainBuilder | `Widget Function(VoidCallback)?` | null | "Try Again" widget |
| loadMoreBuilder | `Widget Function(VoidCallback)?` | null | "Load More" widget |
| retryLimitReached | `Widget?` | null | Retry limit reached widget |

## Contributing

1. Fork the project
2. Create a feature branch:

```bash
git checkout -b feature/AmazingFeature
```

3. Commit changes:

```bash
git commit -m 'Add some AmazingFeature'
```

4. Push to branch:

```bash
git push origin feature/AmazingFeature
```

5. Open a Pull Request

## License

Distributed under the MIT License. See the [LICENSE](LICENSE) file for more information.

## Author

Developed by **Dário Matias**:

- **Portfolio**: [dariomatias-dev](https://dariomatias-dev.com)
- **GitHub**: [dariomatias-dev](https://github.com/dariomatias-dev)
- **Email**: [matiasdario75@gmail.com](mailto:matiasdario75@gmail.com)
- **Instagram**: [@dariomatias_dev](https://instagram.com/dariomatias_dev)
- **LinkedIn**: [linkedin.com/in/dariomatias-dev](https://linkedin.com/in/dariomatias-dev)