indexscroll_listview_builder 2.0.3 copy "indexscroll_listview_builder: ^2.0.3" to clipboard
indexscroll_listview_builder: ^2.0.3 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.

pub package License: MIT

๐Ÿ“ฑ Demo #

IndexScroll ListView Builder 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.3

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'),
  ),
)

Mixing Declarative and Imperative Scrolling #

When using both indexToScrollTo (declarative) and controller.scrollToIndex() (imperative), you may want to force re-scrolling to the same index:

final controller = IndexedScrollController();

IndexScrollListViewBuilder(
  controller: controller,
  itemCount: 100,
  indexToScrollTo: 25,
  forceAutoScroll: true, // Force scroll even if indexToScrollTo unchanged
  itemBuilder: (context, index) => ListTile(title: Text('Item #$index')),
)

// Later, scroll programmatically
await controller.scrollToIndex(75, itemCount: 100);

// Rebuild with same indexToScrollTo will still scroll back to 25
setState(() {}); // forceAutoScroll makes this re-scroll to index 25

๐Ÿงญ 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 viewport
  • 1.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 target
  • 3 - 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 IndexedScrollTag for registration
  • Handles viewport constraints and shrinkWrap logic
  • 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 index
  • register(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
forceAutoScroll bool false Force re-scroll to indexToScrollTo even if value unchanged
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 #

  1. Registration System: Each list item is wrapped with IndexedScrollTag that registers a GlobalKey with the controller
  2. Index Resolution: When scrolling to an index, the controller finds the nearest registered key using smart fallback logic
  3. Viewport Calculation: Uses RenderAbstractViewport.getOffsetToReveal to calculate precise scroll offsets
  4. Off-screen Estimation: For items not yet rendered, estimates position based on visible items and animates there
  5. 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.0 for perfect alignment
  • Last item: Uses maxScrollExtent to 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 const constructors 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.

Q: How do I mix declarative (indexToScrollTo) and imperative (controller.scrollToIndex) scrolling? #

A: Use the forceAutoScroll: true parameter. This forces the list to re-scroll to indexToScrollTo on every rebuild, even if the value hasn't changed. This is useful when you programmatically scroll away using the controller but want rebuilds to restore the original scroll position.

0
likes
160
points
25
downloads

Publisher

unverified uploader

Weekly Downloads

Enhanced ListView.builder with index-based programmatic scrolling, alignment control, offset handling, and optional customizable scrollbar for Flutter.

Repository (GitHub)
View/report issues

Documentation

API reference

License

MIT (license)

Dependencies

flutter, google_fonts, post_frame

More

Packages that depend on indexscroll_listview_builder