infinite_grid 1.1.1
infinite_grid: ^1.1.1 copied to clipboard
A high-performance Flutter package for infinite scrolling grids with direct drag control, optional momentum scrolling, and automatic viewport optimization.
Infinite Grid #
A high-performance Flutter package that implements an infinite scrolling grid UI with direct drag control, optional momentum scrolling, and automatic viewport optimization.
Demo #
Or try the live web demo.
Features #
- High Performance: Optimized rendering with cell preloading and efficient viewport culling
- Momentum Scrolling: Smooth inertial scrolling with customizable physics
- Spiral Indexing: True spiral pattern starting from center (0,0)
- Programmatic Control: Navigate to specific positions or items
- Type-Safe Items: Strongly typed item support with automatic cycling
- Flexible Layout: Configurable cell size and spacing
- Rectangular Cells: Support for both square and rectangular cell dimensions
- Cross-Platform: Works on iOS, Android, Web, and Desktop
Quick Start #
Add this to your pubspec.yaml:
dependencies:
infinite_grid: ^1.1.0
Basic usage:
import 'package:infinite_grid/infinite_grid.dart';
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Square cells
final controller = InfiniteGridController(
layout: const GridLayout(cellSize: 100, spacing: 4),
);
// Or rectangular cells
final rectangularController = InfiniteGridController(
layout: const GridLayout.rectangular(
cellWidth: 120,
cellHeight: 80,
spacing: 4,
),
);
final items = List.generate(50, (index) => 'Item $index');
return InfiniteGrid<String>(
controller: controller,
items: items,
cellBuilder: (context, config, item) => Container(
decoration: BoxDecoration(
color: Colors.blue.shade100,
border: Border.all(color: Colors.blue),
borderRadius: BorderRadius.circular(4),
),
child: Center(child: Text(item)),
),
);
}
}
Usage Examples #
API Reference #
Spiral Indexing #
The grid uses a true spiral indexing pattern starting from center:
Layer 1 (around center):
4 3 2
5 0 1
6 7 8
InfiniteGrid #
Creates a grid that cycles through the provided items infinitely.
InfiniteGrid<T>({
required InfiniteGridController controller,
required List<T> items,
required Widget Function(BuildContext, GridCellConfig, T) cellBuilder,
GridPhysics? gridPhysics,
void Function(Offset)? onPositionChanged,
bool enableMomentumScrolling = false,
int preloadCells = 2,
})
InfiniteGrid.builder #
Creates a grid using a builder pattern, similar to ListView.builder.
InfiniteGrid.builder({
required InfiniteGridController controller,
required int itemCount,
required Widget Function(BuildContext, GridCellConfig, int) cellBuilder,
GridPhysics? gridPhysics,
void Function(Offset)? onPositionChanged,
bool enableMomentumScrolling = false,
int preloadCells = 2,
})
Example:
InfiniteGrid.builder(
controller: controller,
itemCount: 100,
cellBuilder: (context, config, index) => Container(
decoration: BoxDecoration(
color: Colors.blue.shade100,
border: Border.all(color: Colors.blue),
),
child: Center(child: Text('Item $index')),
),
)
Properties
controller: Controller for programmatic control and layout configurationitems: List of items to display in the grid (required)cellBuilder: Builder function for creating cell widgets (receives context, config, and item)gridPhysics: Custom physics for scrolling behavioronPositionChanged: Callback when grid position changesenableMomentumScrolling: Enable/disable momentum scrolling (disabled by default)preloadCells: Number of extra cells to preload around the visible area for smooth scrolling (default: 2)
GridCellConfig #
Configuration object passed to the cell builder.
class GridCellConfig {
final int gridIndex; // Unique cell index
final Point<int> position; // Grid coordinates
final double cellWidth; // Width of the cell
final double cellHeight; // Height of the cell
final Offset globalPosition; // Global position in widget
}
InfiniteGridController #
The controller provides methods for programmatic control of the grid:
InfiniteGridController({
Offset initialPosition = const Offset(0, 0),
GridLayout? layout,
})
initialPosition: Starting position of the grid (default: origin at viewport center)layout: Grid layout configuration for item-aware operations
Factory Constructor
InfiniteGridController.fromItem({
required int initialItem,
required GridLayout layout,
})
Creates a controller starting at a specific item index. The initial position is calculated automatically based on the item index using the provided layout configuration.
initialItem: The item index to start at (uses spiral indexing)layout: Required grid layout configuration for position calculation
Position-Based Methods
jumpTo(Offset position)- Instantly move to a specific positionanimateTo(Offset position, ...)- Animate to a specific positionmoveBy(Offset delta)- Move by a relative offsetanimateBy(Offset delta, ...)- Animate by a relative offsetreset()- Return to the origin (0, 0)
Item-Based Methods
jumpToItem(int itemIndex)- Instantly move to a specific itemanimateToItem(int itemIndex, ...)- Animate to a specific itemgetCurrentCenterItemIndex()- Get the current center item index
Properties
currentPosition- Current position as Offsetlayout- Current grid layout configurationhasClients- Whether the controller is attached to a widget
GridLayout #
Layout configuration for the grid:
// Square cells
const GridLayout({
required double cellSize,
double spacing = 0.0,
})
// Rectangular cells
const GridLayout.rectangular({
required double cellWidth,
required double cellHeight,
double spacing = 0.0,
})
cellSize: Size of each cell in logical pixels (for square cells)cellWidth: Width of each cell in logical pixels (for rectangular cells)cellHeight: Height of each cell in logical pixels (for rectangular cells)spacing: Space between cells in logical pixels
GridPhysics #
Custom physics for momentum scrolling:
const GridPhysics({
double friction = 0.015,
double minVelocity = 50.0,
double maxVelocity = 3000.0,
double decelerationRate = 0.85,
})
Complete Example #
import 'package:flutter/material.dart';
import 'package:infinite_grid/infinite_grid.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Infinite Grid Demo',
home: InfiniteGridDemo(),
);
}
}
class InfiniteGridDemo extends StatefulWidget {
@override
_InfiniteGridDemoState createState() => _InfiniteGridDemoState();
}
class _InfiniteGridDemoState extends State<InfiniteGridDemo> {
late final InfiniteGridController _controller;
@override
void initState() {
super.initState();
_controller = InfiniteGridController(
layout: const GridLayout(cellSize: 100, spacing: 4),
);
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final items = List.generate(1000, (index) => 'Item $index');
return Scaffold(
appBar: AppBar(title: Text('Infinite Grid Demo')),
body: Column(
children: [
Padding(
padding: const EdgeInsets.all(16.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
ElevatedButton(
onPressed: () => _controller.jumpTo(Offset.zero),
child: Text('Go to Origin'),
),
ElevatedButton(
onPressed: () => _controller.animateToItem(100),
child: Text('Go to Item 100'),
),
],
),
),
Expanded(
child: InfiniteGrid<String>(
controller: _controller,
items: items,
cellBuilder: (context, config, item) => Container(
decoration: BoxDecoration(
color: Colors.blue.shade100,
border: Border.all(color: Colors.blue),
borderRadius: BorderRadius.circular(4),
),
child: Center(
child: Text(item),
),
),
),
),
],
),
);
}
}
Performance Tips #
- Use
constconstructors wherever possible for better performance - Optimize cell builders - avoid heavy computations in the builder
- Adjust preload cells based on your needs (more = smoother, less = memory efficient)
- Use appropriate cell sizes for your content to minimize overdraw
License #
MIT License. See LICENSE file for details.
Changelog #
See CHANGELOG.md for details about changes in each version.
Support #
Inspiration #
This package was inspired by the ThiingsGrid React component, adapted for Flutter's widget system and performance characteristics.