positioned_scroll_observer 1.0.1
positioned_scroll_observer: ^1.0.1 copied to clipboard
An elegant scroll observer that support all official slivers could jump/animateToIndex for SliverList/Grid without breaking current widgets.
Features #
- using
jumpToIndexandanimateToIndexto scroll to the specificindex - No breaking for your current sliver widgets, e.g.,
ListView/GridView,SliverList/SliverGrid/SliverAppBar - support almost official
RenderSliverthat has single child or multi children
Getting started #
Use ScrollController #
- create a
ScrollObserver
final ScrollController _controller = ScrollController();
late final ScrollObserver _observer =
ScrollObserver.multiChild(itemCount: _itemCount);
- bind
ScrollObserverwith the item widget/builder that must be wrapped byObserverProxy
ListView.builder(
controller: _controller,
itemBuilder: (context, index) => ObserverProxy(
observer: _observer,
child: ListTile(
key: ValueKey<int>(index),
leading: const CircleAvatar(
child: Text("L"),
),
title: Text("Positioned List Example $index"),
),
),
itemCount: _itemCount,
);
- use
jumpToIndex/animateToIndex
_observer.jumpToIndex(
index,
position: _controller.position,
);
_observer.animateToIndex(
index,
position: _controller.position,
duration: const Duration(milliseconds: 200),
curve: Curves.fastLinearToSlowEaseIn,
);
There you go
Use PositionedScrollController for ListView that only has a single RenderSliver #
- create
PositionedScrollController
final PositionedScrollController _controller =
PositionedScrollController.singleObserver();
- bind
ScrollObserverto item widget/builder
ListView.builder(
controller: _controller,
itemBuilder: (context, index) => ObserverProxy(
observer: _controller.createOrObtainObserver(
itemCount: _itemCount,
),
child: ListTile(
key: ValueKey<int>(index),
leading: const CircleAvatar(
child: Text("L"),
),
title: Text("Positioned List Example $index"),
),
),
itemCount: _itemCount,
);
- use
jumpToIndex/animateToIndex
_controller.jumpToIndex(index);
_controller.animateToIndex(
index,
duration: const Duration(milliseconds: 200),
curve: Curves.fastLinearToSlowEaseIn,
);
There you go
For
ListView.customandGridView.custom, you could also usePositionedChildListDelegateandPositionedChildBuilderDelegatefor wrapping items inObserverProxyconveniently
Usage #
- The item widget/builder must be wrapped using
ObserverProxy ScrollObserverwould observe all children for slivers, e.g.,SliverList/SliverGrid, so all items should have the sameScrollObserverinstead of creating a differentScrollObserverfor each item.
Observing a single sliver #
-
if you want to use
ScrollControllerdirectly, you could create a standaloneScrollObserverby using:ScrollObserver.singleChildfor a sliver with a single child, such asSliverAppBarScrollObserver.multiChildfor a sliver with multi children, such asSliverList/SliverGrid
-
if you prefer using
PositionedScrollControllerthat would manageScrollObservercreated by you, you could create a controller byPositionedScrollController.singleObserver. Then, you could create a standaloneScrollObserverby using:PositionedScrollController.createOrObtainObserver:hasMultiChildindicates if this observer is for a sliver with multi children
Observing multiple slivers (typically for CustomScrollView that has multiple slivers) #
-
if using
ScrollController, you have to create multipleScrollObservers manually and bind them to different slivers. Each sliver should have an uniqueScrollObserverthat must adopt its type: single child or multi children -
if using
PositionedScrollController, you could createPositionedScrollController.multiObserverto manage multipleScrollObservers automatically. Then, usingPositionedScrollController.createOrObtainObserverto create a correspondingScrollObserverfor each sliver.
PositionedScrollController #
It has all methods of ScrollController by extends ScrollController and then help you to manage ScrollObserver.
-
PositionedScrollController.singleObservermanage only a singleScrollObserverthat may have single child or multi children -
PositionedScrollController.multiObservermanage multipleScrollObserverthat may have single child or multi children -
createOrObtainObserver
| parameter | required | default | description |
|---|---|---|---|
| hasMultiChild | YES | true | determine if the ScrollObserver is for a sliver that has multi children |
| itemCount | No | null | the sliver's item count. if null, the observer would behave as a infinite scroll view |
| maxTraceCount | NO | null | the maximum count when tracing ObserverProxy's ancestor RenderSliver and ParentData. Default to 50 internally, only setting it when you ensure you need to trace more nodes. |
| targetToRenderIndex | NO | null | sometimes, the target index to which users want to scroll may not be same as the current render index. By using [targetToRenderIndex], users could define how to map the target index to a render index, e.g., ListView.separated/ReorderableListView. Users could set it on an instance of ScrollObserver not only when creating it. Setting it only when you ensure you need it. |
| renderToTargetIndex | NO | null | same as targetToRenderIndex but in converting reversely. |
jumpToIndexandanimateToIndex. (should passdurationandCurveif usinganimateToIndex)
| parameter | required | default | description |
|---|---|---|---|
| index | YES | N/A | the item's index for a sliver. No effects if ScrollObserver.hasMultiChild is false |
| whichObserver | NO | null | the specific ScrollObserver that is observing a sliver. It is required if ScrollObserver.hasMultiChild is true |
| closeToEdge | YES | true |
try to scroll index at the leading edge if not over scrolling; otherwise, only ensure the index is visible on the screen. |
isVisible: check if the given index is painted on the screen.
| parameter | required | default | description |
|---|---|---|---|
| index | YES | N/A | the specify index you want to check visibility |
| whichObserver | NO | null | the associated ScrollObserver with the index. Required if the controller is PositionedScrollController.multiObserver |
ScrollObserver #
-
ScrollObserver.multiChild: create aScrollObserverthat observes aRenderSliverwith multi children -
ScrollObserver.singleChild: create aScrollObserverthat observes aRenderSliverwith a single child -
jumpToIndexandanimateToIndex. (should passdurationandCurveif usinganimateToIndex)
| parameter | required | default | description |
|---|---|---|---|
| index | YES | N/A | the item's index for a sliver. No effects if ScrollObserver.hasMultiChild is false |
| closeToEdge | YES | true |
try to scroll index at the leading edge if not over scrolling; otherwise, only ensure the index is visible on the screen. |
| position | YES | N/A | the ScrollPosition attached to a ScrollController |