scroll_infinity 0.5.2
scroll_infinity: ^0.5.2 copied to clipboard
ScrollInfinity is a Flutter package that provides a widget with infinite scrolling and paginated loading support, making it easier to build dynamic and endless listings.
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 #
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 – UI toolkit by Google for mobile, web, and desktop
- Dart – Language optimized for fast cross-platform apps
Getting Started #
Install:
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 #
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<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
static const _maxItems = 20;
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: ScrollInfinity<int>(
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 #
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<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
static const _maxItems = 10;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: SizedBox(
height: 100.0,
child: ScrollInfinity<int>(
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 #
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<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
static const _maxItems = 20;
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: ScrollInfinity<int?>(
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<List<T>?> 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<T>? |
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 #
-
Fork the project
-
Create a feature branch:
git checkout -b feature/AmazingFeature
-
Commit changes:
git commit -m 'Add some AmazingFeature'
-
Push to branch:
git push origin feature/AmazingFeature
-
Open a Pull Request
License #
Distributed under the MIT License. See the LICENSE file for more information.
Author #
Developed by Dário Matias:
- Portfolio: dariomatias-dev
- GitHub: dariomatias-dev
- Email: matiasdario75@gmail.com
- Instagram: @dariomatias_dev
- LinkedIn: linkedin.com/in/dariomatias-dev