indexscroll_listview_builder 2.0.0 copy "indexscroll_listview_builder: ^2.0.0" to clipboard
indexscroll_listview_builder: ^2.0.0 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](https://img.shields.io/pub/v/indexscroll_listview_builder.svg)](https://pub.dev/packages/indexscroll_listview_builder)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

## ๐Ÿ“ฑ Demo

![IndexScroll ListView Builder Demo](https://raw.githubusercontent.com/SoundSliced/indexscroll_listview_builder/main/example/assets/example.gif)

*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

## ๐Ÿ†• What's New in 2.0.0

### Major Improvements

* โœ… **Fixed bidirectional scrolling**: Now works perfectly scrolling both up and down
* โœ… **Fixed external controller**: Buttons now scroll the correct ListView (not the outer page)
* โœ… **Viewport-based implementation**: Precise control using `RenderAbstractViewport.getOffsetToReveal`
* โœ… **Smart off-screen handling**: Estimates position for items not yet rendered
* โœ… **Operation cancellation**: Prevents interrupted animations during rapid scrolling
* โœ… **Performance optimized**: Fast-path index resolution for common cases

### Breaking Change

The `scrollToIndex()` method now requires an `itemCount` parameter:

```dart
// v1.x
controller.scrollToIndex(50);

// v2.0.0
controller.scrollToIndex(50, itemCount: totalItems);
```

This enables accurate position estimation for off-screen items.

## ๐Ÿ›  Installation

Add to your `pubspec.yaml`:

```yaml
dependencies:
  indexscroll_listview_builder: ^2.0.0
```

Then import:

```dart
import 'package:indexscroll_listview_builder/indexscroll_listview_builder.dart';
```

## ๐Ÿš€ Quick Start

```dart
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:

```dart
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:

```dart
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

```dart
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:
```dart
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:
```bash
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 `GlobalKey`s 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

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.

0
likes
0
points
57
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

License

unknown (license)

Dependencies

flutter, google_fonts, post_frame

More

Packages that depend on indexscroll_listview_builder