anchored_list 0.2.0
anchored_list: ^0.2.0 copied to clipboard
Jump to any index in a lazy list in constant time, and hold your place when items arrive above it. One viewport anchored at the target, not two lists cross-fading.
0.2.0 #
An audit of every package in this repo found six defects here, including one in the feature this package exists for. Worth taking.
Fixed #
- A prepend was silently dropped when the anchor sat near the end of the
list.
itemsInsertedAboveclamped the new anchor againstitemCount— but it runs between yoursetStateand the rebuild that delivers the longer list, so that count is still the old one. A chat pinned to the newest message is the worst case and the flagship one: the shift was clamped away entirely and the reader's content slid down the screen, which is the exact lurch this API exists to prevent. The anchor is now held unclamped and clamped on read, so the intent survives until the real count arrives. Every prepend test anchored mid-list, so nothing caught it; there is now one anchored at the last item. - An item built with a
GlobalKeycrashed the list. The child's key was copied onto the wrapper widget, leaving two live elements registered under the same key: "Multiple widgets used the same GlobalKey" on the first frame. Keys are now salted before being lifted, the waySliverChildBuilderDelegatedoes it, and unsalted again beforefindChildIndexCallbacksees them. reverse: trueput the whole padding in a gap at the anchor. The inset was split by scroll axis alone, ignoringreverseand directionality, so under a reversed list — the standard chat layout — both anchor-facing edges were the ones kept: a blank band mid-content, and no padding at either end. The split now resolves the real axis direction first.animateToIndexovershot by about a screenful × alignment. Alignment was consumed twice, once as the viewport anchor and once byensureVisible, which never reads the anchor. OnlyensureVisibleconsumes it now.jumpToIndexaligned the item's leading edge, not the item. So0.5was not centred and1.0scrolled the target off-screen, whileanimateToIndexaligned the box — the example had two adjacent buttons disagreeing on the same argument. Both now mean whatScrollable.ensureVisiblemeans.
0.1.1 #
Packaging only — no API or behaviour changes.
- The demo animations now ship inside the package, so they appear as screenshots on the pub.dev page rather than only in the README on GitHub.
.pubignoreexcludes the raw recorder frames, so shipping them costs about 440 KB rather than the 11 MB the frame directory would have added.
0.1.0 #
Initial release.
Jumping
AnchoredList.builder— a lazy list that jumps to any index in constant time, by re-anchoring a centre sliver rather than cross-fading two lists.AnchoredListControllerwithjumpToIndex,animateToIndexandanchorIndex.- One viewport and one set of children, so there is no transition artefact and nothing is built twice.
Holding position while the list changes
itemsInsertedAboveanditemsRemovedAbovekeep the viewport pixel-still when items arrive at or leave the top of the list. Because the anchor is an index, the correction is arithmetic on one integer and the scroll offset is never touched — nothing moves on screen, even mid-item.findChildIndexCallbacklocates items by key so their state survives insertions, translated across the two slivers for you.
Reaching the scroll position
scrollControllermay be supplied, andAnchoredListController .scrollControllerreturns whichever one is in use — enough for aScrollbar, page-up/page-down, or linking two lists.- Offsets are measured from the anchor, so zero is the anchored item and content above it is at negative offset.
Reporting
itemPositionsreports each built item's place as a fraction of the viewport, withisVisible,isFullyVisibleandextent.
The rest of the ListView surface
AnchoredList.separatedandAnchoredList(children: [...]).padding,physics,reverse,scrollDirection,cacheExtent,semanticChildCount,dragStartBehavior,keyboardDismissBehavior,scrollBehavior,clipBehavior,restorationIdand the threeadd*flags.paddingis split between the two slivers rather than applied to both, which would double the inset at the anchor.- Semantic indexes are translated, so items above the anchor announce their real list index instead of counting backwards from it.
Not supported: shrinkWrap, and this is not a sliver. Flutter asserts
!shrinkWrap || center == null, so a centre-anchored viewport cannot size to
its content — the parameter is absent rather than present and broken.