indexscroll_listview_builder 2.0.2
indexscroll_listview_builder: ^2.0.2 copied to clipboard
Enhanced ListView.builder with index-based programmatic scrolling, alignment control, offset handling, and optional customizable scrollbar for Flutter.
indexscroll_listview_builder #
Enhanced ListView.builder for Flutter with powerful bidirectional index-based programmatic scrolling, precise viewport control, item alignment, offset handling, and optional customizable scrollbar.
๐ฑ Demo #

Interactive demonstration showing bidirectional scrolling, auto-scroll with alignment control, and external controller buttons
โจ Features #
- ๐ฏ Bidirectional scrolling: Scroll to any item by index - works perfectly both up and down the list
- ๐ Viewport-based precision: Direct viewport offset calculations for accurate positioning
- โก Off-screen item support: Scroll to items not yet rendered with smart position estimation
- ๐ฎ Automatic initial scroll: Navigate to target index on widget build via
indexToScrollTo - ๐ Offset support: Keep items before the target visible (
numberOfOffsetedItemsPriorToSelectedItem) - ๐จ Customizable alignment: Position target item anywhere in viewport with
scrollAlignment(0.0โ1.0) - ๐น๏ธ External controller: Advanced programmatic control with
IndexedScrollController - ๐ Optional scrollbar: Full customization (thumb, track, thickness, radius, orientation)
- ๐ Operation cancellation: Superseded scroll operations are cancelled to prevent interrupted animations
- ๐ฑ Smart
shrinkWrap: Automatic handling for unbounded constraints - โจ Smooth animations: Configurable duration and curve
- ๐ฌ Frame-delayed execution: Reduces layout jank during scroll operations
๐ Installation #
Add to your pubspec.yaml:
dependencies:
indexscroll_listview_builder: ^2.0.2
Then import:
import 'package:indexscroll_listview_builder/indexscroll_listview_builder.dart';
๐ Quick Start #
IndexScrollListViewBuilder(
itemCount: 100,
itemBuilder: (context, index) => ListTile(title: Text('Item #$index')),
)
๐ฏ Auto Scroll on Build #
Automatically scroll to a target index when the widget builds:
IndexScrollListViewBuilder(
itemCount: 50,
indexToScrollTo: 25, // scroll after first frame
numberOfOffsetedItemsPriorToSelectedItem: 2, // keep previous 2 items visible
itemBuilder: (context, index) => ListTile(
title: Text('Item #$index'),
),
)
๐งญ External Controller #
Use an IndexedScrollController for programmatic control:
final controller = IndexedScrollController();
final itemCount = 100;
IndexScrollListViewBuilder(
controller: controller,
itemCount: itemCount,
itemBuilder: (context, index) => ListTile(title: Text('Item #$index')),
);
// Later (e.g. button press)
await controller.scrollToIndex(75, itemCount: itemCount, alignmentOverride: 0.3);
// Scroll to first item
await controller.scrollToIndex(0, itemCount: itemCount);
// Scroll to last item
await controller.scrollToIndex(itemCount - 1, itemCount: itemCount);
๐ช Scrollbar Example #
IndexScrollListViewBuilder(
itemCount: 80,
showScrollbar: true,
scrollbarThumbVisibility: true,
scrollbarThickness: 8,
scrollbarRadius: const Radius.circular(8),
itemBuilder: (context, index) => ListTile(title: Text('Item #$index')),
)
๐ Alignment & Offset #
scrollAlignment #
Controls where the target item appears in the viewport:
0.0- Item aligns at the start (top for vertical, left for horizontal)0.5- Item appears centered in the viewport1.0- Item aligns at the end (bottom for vertical, right for horizontal)- Default:
0.2(20% from start)
numberOfOffsetedItemsPriorToSelectedItem #
Shifts the scroll position backward to keep previous items visible:
1- Shows the target item (default)2- Shows 1 item before the target3- Shows 2 items before the target- etc.
Example:
IndexScrollListViewBuilder(
indexToScrollTo: 50,
numberOfOffsetedItemsPriorToSelectedItem: 3, // Shows items 48, 49, 50
scrollAlignment: 0.0, // Items 48-50 appear at top
itemCount: 100,
itemBuilder: (context, index) => ListTile(title: Text('Item $index')),
)
๐งช Example Application #
See the complete interactive example in example/lib/main.dart demonstrating:
- Basic List: Simple list with 100 items
- Auto-scroll Demo: Dynamic target selection with slider, offset control, and alignment settings
- External Controller: Comprehensive button controls:
- Scroll to First/Last item
- Jump +10/-10 items
- Direct index input
- Perfect handling of list boundaries
Run the example:
cd example
flutter run
๐ API Overview #
IndexScrollListViewBuilder #
Primary widget that extends ListView.builder with index-based scrolling capabilities.
Key Methods:
- Automatically wraps items with
IndexedScrollTagfor registration - Handles viewport constraints and
shrinkWraplogic - Manages scroll controller lifecycle
IndexedScrollController #
Core controller that powers the scrolling mechanism.
Key Methods:
scrollToIndex(int index, {required int itemCount, double? alignmentOverride})- Scroll to specific indexregister(int index, GlobalKey key)- Register an item (called internally)unregister(int index)- Unregister an item (called internally)
Features:
- Maintains registry of
GlobalKeys for each list item - Smart index resolution with fallback logic
- Viewport-based offset calculation
- Operation versioning for cancellation
- Special handling for list extremes (first/last items)
IndexedScrollTag #
Internal widget that tags each list item for the controller.
Lifecycle:
- Registers item on
initState - Updates registration on index/controller changes
- Unregisters on
dispose
โ Parameters #
Core Parameters #
| Parameter | Type | Default | Description |
|---|---|---|---|
itemCount |
int |
Required | Total number of items in the list |
itemBuilder |
Widget Function(BuildContext, int) |
Required | Builder function for list items |
indexToScrollTo |
int? |
null |
Auto-scroll target index after build |
controller |
IndexedScrollController? |
null |
External controller for programmatic scrolling |
Scrolling Behavior #
| Parameter | Type | Default | Description |
|---|---|---|---|
numberOfOffsetedItemsPriorToSelectedItem |
int |
1 |
Number of items to keep visible before target |
scrollAlignment |
double? |
0.2 |
Target item alignment in viewport (0.0โ1.0) |
scrollAnimationDuration |
Duration |
400ms |
Animation duration for scrolling |
scrollDirection |
Axis? |
Axis.vertical |
Scroll direction (vertical/horizontal) |
physics |
ScrollPhysics? |
BouncingScrollPhysics |
Scroll physics |
shrinkWrap |
bool? |
Auto | Whether to shrink-wrap content (auto-detected) |
Scrollbar Customization #
| Parameter | Type | Default | Description |
|---|---|---|---|
showScrollbar |
bool |
false |
Whether to display scrollbar |
scrollbarThumbVisibility |
bool? |
null |
Force scrollbar thumb visibility |
scrollbarTrackVisibility |
bool? |
null |
Force scrollbar track visibility |
scrollbarThickness |
double? |
Platform default | Scrollbar thickness in pixels |
scrollbarRadius |
Radius? |
Platform default | Scrollbar corner radius |
scrollbarOrientation |
ScrollbarOrientation? |
null |
Which side to show scrollbar |
scrollbarInteractive |
bool? |
true |
Whether scrollbar can be dragged |
suppressPlatformScrollbars |
bool |
false |
Hide platform-specific scrollbars |
Advanced Options #
| Parameter | Type | Default | Description |
|---|---|---|---|
padding |
EdgeInsetsGeometry? |
EdgeInsets.zero |
List content padding |
autoScrollMaxFrameDelay |
int? |
Controller default | Max frames to wait before auto-scroll |
autoScrollEndOfFrameDelay |
int? |
Controller default | Frames to wait at end of auto-scroll |
๏ฟฝ Technical Details #
How It Works #
- Registration System: Each list item is wrapped with
IndexedScrollTagthat registers aGlobalKeywith the controller - Index Resolution: When scrolling to an index, the controller finds the nearest registered key using smart fallback logic
- Viewport Calculation: Uses
RenderAbstractViewport.getOffsetToRevealto calculate precise scroll offsets - Off-screen Estimation: For items not yet rendered, estimates position based on visible items and animates there
- Operation Versioning: Each scroll operation gets a version number; superseded operations are cancelled
Edge Cases Handled #
- First item (index 0): Always scrolls to offset
0.0for perfect alignment - Last item: Uses
maxScrollExtentto ensure full visibility - Rapid scrolling: Operation cancellation prevents interrupted animations
- Off-screen items: Position estimation enables scrolling before item is built
- Dynamic lists: Handles controller and index changes gracefully
Performance Considerations #
- Fast-path optimization: Checks exact index before searching all registered keys
- Const constructors: All widgets use
constconstructors where possible - Key caching: GlobalKeys are created once and reused across rebuilds
- Frame-delayed execution: Reduces layout jank during scroll operations
๏ฟฝ๐ CHANGELOG #
See CHANGELOG.md for detailed version history.
๐ License #
Licensed under the MIT License. See LICENSE.
๐ Repository & Issues #
Repository: https://github.com/SoundSliced/indexscroll_listview_builder
Issues: https://github.com/SoundSliced/indexscroll_listview_builder/issues
๐ Contributing #
Contributions welcome! Feel free to open issues or PRs for improvements, examples, or documentation refinements.
If this package helps you, Like it on Pub.dev, and add a โญ on GitHub. This is appreciated!
โ FAQ #
Q: Can I scroll to items that haven't been built yet? #
A: Yes! Version 2.0.0 estimates the position of off-screen items and scrolls there smoothly.
Q: Why does scrollToIndex require itemCount in v2.0.0? #
A: The itemCount parameter enables accurate position estimation for off-screen items, especially when scrolling to the last item or items near the end.
Q: How do I scroll to the exact last item? #
A: Use controller.scrollToIndex(itemCount - 1, itemCount: itemCount). The controller automatically uses maxScrollExtent for the last index.
Q: What happens if I scroll rapidly or drag a slider? #
A: Version 2.0.0 includes operation versioning that cancels superseded scroll operations, ensuring smooth animations without interruption.
Q: Can I use this with horizontal lists? #
A: Yes! Set scrollDirection: Axis.horizontal and the package handles everything correctly.
Q: Does this work with dynamic lists that change size? #
A: Yes, the registration system automatically handles items being added or removed. The controller maintains a registry that updates as widgets are built/disposed.