Skip to content

Commit

Permalink
docs: update README (#15)
Browse files Browse the repository at this point in the history
  • Loading branch information
knopp authored Feb 18, 2024
1 parent 845e559 commit f43cdaf
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 6 deletions.
139 changes: 134 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,138 @@
Experimental drop-in replacement for `SliverList` that can handle arbitrary number of items with variable extents.
# SliverList and ListView - Supercharged

## Example
> See the [live example](https://superlistapp.github.io/super_sliver_list/#/) of `SuperSliverList`.
`SuperSliverList` and `SuperListView` are drop in replacement widgets for `SliverList` and `ListView` with greatly improved performance and additional features:

#### Fast scrolling with large amount of items with variable extents

`SliverList` performance degrades heavily when quickly scrolling through a large amount of items with different extents, requiring workarounds such as using `FixedExtentSliverList` or prototype items. `SuperSliverList` uses different layout algorithm and can handle virtually unlimited number of items with variable extents without any slow-downs.

#### Ability to jump or animate to specific item

`SliverList` does not provide any way to jump or animate a particular index. There is a [scrollable_positioned_list](https://pub.dev/packages/scrollable_positioned_list) package that provides this functionality, but it comes at a cost, as it requires custom scroll view, does not seem to work properly with Scrollbars, can't be used with with other slivers (such as sticky headers) and ultimately is backed by a `SliverList` so it has the same performance issues as mentioned above.

`SuperSliverList` provides a way to reliably jump and animate to a specific item, even if the item is outside of the viewport and has not been built or laid out yet.

#### Smooth and predictable scrollbar behavior

`SliverList` is quite prone to scrollbar erraticaly jumping around when scrolling through a list of items with different extents. With `SuperSliverList` the scrollbar should behave more predictably. See the [Advanced](#advanced) section for more details.

## Basic Usage

`SuperListView` is a drop-in replacement for `ListView`, and as such you can use it same way you'd use `ListView`:

```dart
SuperListView.builder(
itemCount: 1000,
itemBuilder: (context, index) {
return ListTile(title: Text('Item $index'));
},
)
```

`SuperSliverList` is a drop-in replacement for `SliverList` and should work with any `CustomScrollView` configuration:
```dart
CustomScrollView(
slivers: <Widget>[
SliverPadding(
padding: const EdgeInsets.all(20.0),
sliver: SuperSliverList(
delegate: SliverChildListDelegate(
<Widget>[
const Text("I'm dedicating every day to you"),
const Text('Domestic life was never quite my style'),
const Text('When you smile, you knock me out, I fall apart'),
const Text('And I thought I was so smart'),
],
),
),
),
],
)
```

## Jumping and animating to specific item

`ExtentController` can be provided to `SuperSliverList`/`SuperListView` and later used to jump or animate to specific item:

```dart
class _MyState extends State<MyWidget> {
final _extentController = ExtentController();
final _scrollController = ScrollController();
You can view live example that compares `SuperSliverList` with `SliverList` [here](https://superlistapp.github.io/super_sliver_list/#/). Try dragging scrollbar to see the difference.
@override
Widget build(BuildContext context) {
return SuperListView.builder(
extentController: _extentController,
controller: _scrollController,
itemCount: 1000,
itemBuilder: (context, index) {
return ListTile(title: Text('Item $index'));
},
);
}
## Usage
void jumpToItem(int index) {
_extentController.jumpToItem(
index: index,
scrollController: _scrollController,
alignment: 0.5,
);
}
void animateToItem(int index) {
_extentController.animateToItem(
index: index,
scrollController: _scrollController,
alignment: 0.5,
// You can provide duration and curve depending on the estimated
// distance between currentPosition and the target item position.
duration: (estimatedDistance) => Duration(milliseconds: 250),
curve: (estimatedDistance) => Curves.easeInOut,
);
}
}
```

## Advanced

Very roughtly speaking `SuperSliverList` works by estimating the extent of items that are outside of viewport and when these items are scrolled into the viewport cache area the scroll position is transparently adjusted to account of the difference between estimated and actual extents. On small lists this difference may result in scrollbar movement not being perfectly aligned with list movement. `SuperSliverList` provides two ways to rectify this:

### Improve extent estimation

You can register custom callback that will be used to estimate extent of estimated items. This can be useful if you have an idea, atleast approximately, how large the extent of each item is.

```dart
SuperSliverList(
delegate: /*...*/,
estimateExtent: (index) => 100.0, // Provide your own extent estimation
)
```

### Precalculate extents for items

`SuperSliverList` can, if needed, asynchronously precalculate extents for items. To enfore this, subclass `ExtentPrecalculationPolicy` and provide it to `SuperSliverList`:

In this example the extents are precalculated for lists with less than 100 items:

```dart
class MyPrecalculationPolicy extends ExtentPrecalculationPolicy {
@override
bool shouldPrecaculateExtents(ExtentPrecalculationContext context) {
return context.numberOfItems < 100;
}
}
return SuperSliverList(
delegate: /*...*/,
extentPrecalculationPolicy: myPolicy,
)
```

The threshold is arbitrary, but in general there are diminishing returns for precalculating extents for large lists, as the extent estimation error for each item has much smaller impact on the scrollbar position if there are many items.

## Example

See the [example](example) for a complete sample app using `SuperSliverList`.
See the [example](example) folder for a complete sample app using `SuperSliverList`. You can also see the [example deployed live](https://superlistapp.github.io/super_sliver_list/).
2 changes: 1 addition & 1 deletion lib/src/list_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,7 @@ import "super_sliver_list.dart";
/// return Scaffold(
/// appBar: AppBar(title: const Text('Empty List Test')),
/// body: itemCount > 0
/// ? ListView.builder(
/// ? SuperListView.builder(
/// itemCount: itemCount,
/// itemBuilder: (BuildContext context, int index) {
/// return ListTile(
Expand Down

0 comments on commit f43cdaf

Please sign in to comment.