From 51e0b90f941ab84fc58690504252915d718b3d96 Mon Sep 17 00:00:00 2001 From: Gordon Hayes Date: Mon, 18 Oct 2021 10:51:06 +0200 Subject: [PATCH] chore: linting --- .../src/element_registry.dart | 4 +- .../src/indexed_key.dart | 13 +- .../src/item_positions_listener.dart | 6 +- .../src/item_positions_notifier.dart | 2 +- .../src/positioned_list.dart | 44 +-- .../src/post_mount_callback.dart | 2 +- .../src/scroll_view.dart | 7 +- .../src/scrollable_positioned_list.dart | 162 +++++----- .../src/viewport.dart | 80 ++--- .../reversed_positioned_list_test.dart | 2 +- .../scrollable_positioned_list_test.dart | 303 ++++++++---------- ...rated_scrollable_positioned_list_test.dart | 66 ++-- 12 files changed, 333 insertions(+), 358 deletions(-) diff --git a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/element_registry.dart b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/element_registry.dart index b24a0c17..f4327246 100644 --- a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/element_registry.dart +++ b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/element_registry.dart @@ -46,12 +46,12 @@ class _RegistryWidgetState extends State { } class _InheritedRegistryWidget extends InheritedWidget { - final _RegistryWidgetState state; - const _InheritedRegistryWidget( {Key? key, required this.state, required Widget child}) : super(key: key, child: child); + final _RegistryWidgetState state; + @override bool updateShouldNotify(InheritedWidget oldWidget) => true; } diff --git a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/indexed_key.dart b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/indexed_key.dart index 689996d0..bbff45c2 100644 --- a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/indexed_key.dart +++ b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/indexed_key.dart @@ -2,10 +2,13 @@ import 'dart:ui' show hashValues; import 'package:flutter/foundation.dart'; +/// {@template indexed_key} +/// Creates an indexed key that delegates its [operator==] to the given key. +/// +/// It contains an index used in [ScrollablePositionedList]. +/// {@endtemplate} class IndexedKey extends LocalKey { - /// Creates an indexed key that delegates its [operator==] to the given key. - /// - /// It contains an index used in [ScrollablePositionedList]. + /// {@macro indexed_key} const IndexedKey(this.key, this.index); /// The key to which this this delegates its [operator==]. @@ -24,7 +27,5 @@ class IndexedKey extends LocalKey { int get hashCode => hashValues(runtimeType, key); @override - String toString() { - return '(IndexedKey) index: $index, key: $key'; - } + String toString() => '(IndexedKey) index: $index, key: $key'; } diff --git a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/item_positions_listener.dart b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/item_positions_listener.dart index dfb3e7d8..886cabe7 100644 --- a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/item_positions_listener.dart +++ b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/item_positions_listener.dart @@ -4,8 +4,8 @@ import 'package:flutter/foundation.dart'; -import 'item_positions_notifier.dart'; -import 'scrollable_positioned_list.dart'; +import 'package:stream_chat_flutter/src/scrollable_positioned_list/src/item_positions_notifier.dart'; +import 'package:stream_chat_flutter/src/scrollable_positioned_list/src/scrollable_positioned_list.dart'; /// Provides a listenable iterable of [itemPositions] of items that are on /// screen and their locations. @@ -57,5 +57,5 @@ class ItemPosition { @override String toString() => - 'ItemPosition(index: $index, itemLeadingEdge: $itemLeadingEdge, itemTrailingEdge: $itemTrailingEdge)'; + '''ItemPosition(index: $index, itemLeadingEdge: $itemLeadingEdge, itemTrailingEdge: $itemTrailingEdge)'''; } diff --git a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/item_positions_notifier.dart b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/item_positions_notifier.dart index a2b993a6..172426a5 100644 --- a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/item_positions_notifier.dart +++ b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/item_positions_notifier.dart @@ -4,7 +4,7 @@ import 'package:flutter/foundation.dart'; -import 'item_positions_listener.dart'; +import 'package:stream_chat_flutter/src/scrollable_positioned_list/src/item_positions_listener.dart'; /// Internal implementation of [ItemPositionsListener]. class ItemPositionsNotifier implements ItemPositionsListener { diff --git a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/positioned_list.dart b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/positioned_list.dart index c53f017e..43f3d9ab 100644 --- a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/positioned_list.dart +++ b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/positioned_list.dart @@ -8,11 +8,11 @@ import 'package:flutter/rendering.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/widgets.dart'; -import 'element_registry.dart'; -import 'indexed_key.dart'; -import 'item_positions_listener.dart'; -import 'item_positions_notifier.dart'; -import 'scroll_view.dart'; +import 'package:stream_chat_flutter/src/scrollable_positioned_list/src/element_registry.dart'; +import 'package:stream_chat_flutter/src/scrollable_positioned_list/src/indexed_key.dart'; +import 'package:stream_chat_flutter/src/scrollable_positioned_list/src/item_positions_listener.dart'; +import 'package:stream_chat_flutter/src/scrollable_positioned_list/src/item_positions_notifier.dart'; +import 'package:stream_chat_flutter/src/scrollable_positioned_list/src/scroll_view.dart'; /// A list of widgets similar to [ListView], except scroll control /// and position reporting is based on index rather than pixel offset. @@ -27,6 +27,7 @@ import 'scroll_view.dart'; class PositionedList extends StatefulWidget { /// Create a [PositionedList]. const PositionedList({ + Key? key, required this.itemCount, required this.itemBuilder, this.separatorBuilder, @@ -44,11 +45,12 @@ class PositionedList extends StatefulWidget { this.addSemanticIndexes = true, this.addRepaintBoundaries = true, this.addAutomaticKeepAlives = true, - }) : assert(itemCount != null), - assert(itemBuilder != null), - assert((positionedIndex == 0) || (positionedIndex < itemCount)); + }) : assert((positionedIndex == 0) || (positionedIndex < itemCount), + 'positionedIndex cannot be 0 and must be smaller than itemCount'), + super(key: key); - /// Called to find the new index of a child based on its key in case of reordering. + /// Called to find the new index of a child based on its key in case of + /// reordering. /// /// If not provided, a child widget may not map to its existing [RenderObject] /// when the order in which children are returned from [builder] changes. @@ -263,7 +265,7 @@ class _PositionedListState extends State { : widget.reverse ? widget.padding?.copyWith(left: 0) : widget.padding?.copyWith(right: 0)) ?? - EdgeInsets.all(0); + const EdgeInsets.all(0); EdgeInsets get _centerSliverPadding => widget.scrollDirection == Axis.vertical ? widget.reverse @@ -274,13 +276,13 @@ class _PositionedListState extends State { bottom: widget.positionedIndex == 0 ? widget.padding!.bottom : 0) ?? - EdgeInsets.all(0) + const EdgeInsets.all(0) : widget.padding?.copyWith( top: widget.positionedIndex == 0 ? widget.padding!.top : 0, bottom: widget.positionedIndex == widget.itemCount - 1 ? widget.padding!.bottom : 0) ?? - EdgeInsets.all(0) + const EdgeInsets.all(0) : widget.reverse ? widget.padding?.copyWith( left: widget.positionedIndex == widget.itemCount - 1 @@ -289,23 +291,23 @@ class _PositionedListState extends State { right: widget.positionedIndex == 0 ? widget.padding!.right : 0) ?? - EdgeInsets.all(0) + const EdgeInsets.all(0) : widget.padding?.copyWith( left: widget.positionedIndex == 0 ? widget.padding!.left : 0, right: widget.positionedIndex == widget.itemCount - 1 ? widget.padding!.right : 0, ) ?? - EdgeInsets.all(0); + const EdgeInsets.all(0); EdgeInsets get _trailingSliverPadding => widget.scrollDirection == Axis.vertical ? widget.reverse - ? widget.padding?.copyWith(bottom: 0) ?? EdgeInsets.all(0) - : widget.padding?.copyWith(top: 0) ?? EdgeInsets.all(0) + ? widget.padding?.copyWith(bottom: 0) ?? const EdgeInsets.all(0) + : widget.padding?.copyWith(top: 0) ?? const EdgeInsets.all(0) : widget.reverse - ? widget.padding?.copyWith(right: 0) ?? EdgeInsets.all(0) - : widget.padding?.copyWith(left: 0) ?? EdgeInsets.all(0); + ? widget.padding?.copyWith(right: 0) ?? const EdgeInsets.all(0) + : widget.padding?.copyWith(left: 0) ?? const EdgeInsets.all(0); void _schedulePositionNotificationUpdate() { if (!updateScheduled) { @@ -317,10 +319,10 @@ class _PositionedListState extends State { } final positions = []; RenderViewport? viewport; - for (var element in registeredElements.value!) { - final RenderBox box = element.renderObject as RenderBox; + for (final element in registeredElements.value!) { + final box = element.renderObject as RenderBox; viewport ??= RenderAbstractViewport.of(box) as RenderViewport?; - final IndexedKey key = element.widget.key as IndexedKey; + final key = element.widget.key as IndexedKey; if (widget.scrollDirection == Axis.vertical) { final reveal = viewport!.getOffsetToReveal(box, 0).offset; final itemOffset = reveal - diff --git a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/post_mount_callback.dart b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/post_mount_callback.dart index 9ec553fa..ddb3e3d4 100644 --- a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/post_mount_callback.dart +++ b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/post_mount_callback.dart @@ -29,7 +29,7 @@ class _PostMountCallbackElement extends StatelessElement { @override void mount(Element? parent, dynamic newSlot) { super.mount(parent, newSlot); - final PostMountCallback postMountCallback = widget as PostMountCallback; + final postMountCallback = widget as PostMountCallback; postMountCallback.callback?.call(); } } diff --git a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/scroll_view.dart b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/scroll_view.dart index e00462e2..9adacfeb 100644 --- a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/scroll_view.dart +++ b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/scroll_view.dart @@ -6,11 +6,14 @@ import 'package:flutter/gestures.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; -import 'viewport.dart'; +import 'package:stream_chat_flutter/src/scrollable_positioned_list/src/viewport.dart'; -/// A version of [CustomScrollView] that allows does not constrict the extents +/// {@template custom_scroll_view} +/// A version of [CustomScrollView] that does not constrict the extents /// to be within 0 and 1. See [CustomScrollView] for more information. +/// {@endtemplate} class UnboundedCustomScrollView extends CustomScrollView { + /// {@macro custom_scroll_view} const UnboundedCustomScrollView({ Key? key, Axis scrollDirection = Axis.vertical, diff --git a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/scrollable_positioned_list.dart b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/scrollable_positioned_list.dart index d262578b..704ed221 100644 --- a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/scrollable_positioned_list.dart +++ b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/scrollable_positioned_list.dart @@ -10,10 +10,10 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/widgets.dart'; -import 'item_positions_listener.dart'; -import 'item_positions_notifier.dart'; -import 'positioned_list.dart'; -import 'post_mount_callback.dart'; +import 'package:stream_chat_flutter/src/scrollable_positioned_list/src/item_positions_listener.dart'; +import 'package:stream_chat_flutter/src/scrollable_positioned_list/src/item_positions_notifier.dart'; +import 'package:stream_chat_flutter/src/scrollable_positioned_list/src/positioned_list.dart'; +import 'package:stream_chat_flutter/src/scrollable_positioned_list/src/post_mount_callback.dart'; /// Number of screens to scroll when scrolling a long distance. const int _screenScrollCount = 2; @@ -52,9 +52,7 @@ class ScrollablePositionedList extends StatefulWidget { this.addRepaintBoundaries = true, this.minCacheExtent, this.findChildIndexCallback, - }) : assert(itemCount != null), - assert(itemBuilder != null), - itemPositionsNotifier = itemPositionsListener as ItemPositionsNotifier?, + }) : itemPositionsNotifier = itemPositionsListener as ItemPositionsNotifier?, separatorBuilder = null, super(key: key); @@ -79,13 +77,12 @@ class ScrollablePositionedList extends StatefulWidget { this.addRepaintBoundaries = true, this.minCacheExtent, this.findChildIndexCallback, - }) : assert(itemCount != null), - assert(itemBuilder != null), - assert(separatorBuilder != null), + }) : assert(separatorBuilder != null, 'seperatorBuilder cannot be null'), itemPositionsNotifier = itemPositionsListener as ItemPositionsNotifier?, super(key: key); - /// Called to find the new index of a child based on its key in case of reordering. + /// Called to find the new index of a child based on its key in case of + /// reordering. /// /// If not provided, a child widget may not map to its existing [RenderObject] /// when the order in which children are returned from [builder] changes. @@ -235,9 +232,11 @@ class ItemScrollController { Curve curve = Curves.linear, List opacityAnimationWeights = const [40, 20, 40], }) { - assert(_scrollableListState != null); - assert(opacityAnimationWeights.length == 3); - assert(duration > Duration.zero); + assert(_scrollableListState != null, '_scrollableListState cannot be null'); + assert(opacityAnimationWeights.length == 3, + 'opacityAnimationWeights.length is not equal to 3'); + assert(duration > Duration.zero, + 'duration needs to be bigger than Duration.zero'); return _scrollableListState!._scrollTo( index: index, alignment: alignment, @@ -248,7 +247,8 @@ class ItemScrollController { } void _attach(_ScrollablePositionedListState scrollableListState) { - assert(_scrollableListState == null); + assert( + _scrollableListState == null, '_scrollableListState needs to be null'); _scrollableListState = scrollableListState; } @@ -260,11 +260,11 @@ class ItemScrollController { class _ScrollablePositionedListState extends State with TickerProviderStateMixin { /// Details for the primary (active) [ListView]. - var primary = _ListDisplayDetails(const ValueKey('Ping')); + _ListDisplayDetails primary = _ListDisplayDetails(const ValueKey('Ping')); /// Details for the secondary (transitional) [ListView] that is temporarily /// shown when scrolling a long distance. - var secondary = _ListDisplayDetails(const ValueKey('Pong')); + _ListDisplayDetails secondary = _ListDisplayDetails(const ValueKey('Pong')); final opacity = ProxyAnimation(const AlwaysStoppedAnimation(0)); @@ -275,10 +275,11 @@ class _ScrollablePositionedListState extends State @override void initState() { super.initState(); - ItemPosition? initialPosition = PageStorage.of(context)!.readState(context); - primary.target = initialPosition?.index ?? widget.initialScrollIndex; - primary.alignment = - initialPosition?.itemLeadingEdge ?? widget.initialAlignment; + final ItemPosition? initialPosition = + PageStorage.of(context)!.readState(context); + primary + ..target = initialPosition?.index ?? widget.initialScrollIndex + ..alignment = initialPosition?.itemLeadingEdge ?? widget.initialAlignment; if (widget.itemCount > 0 && primary.target > widget.itemCount - 1) { primary.target = widget.itemCount - 1; } @@ -333,79 +334,78 @@ class _ScrollablePositionedListState extends State } @override - Widget build(BuildContext context) { - return LayoutBuilder( - builder: (context, constraints) { - final cacheExtent = _cacheExtent(constraints); - return GestureDetector( - onPanDown: (_) => _stopScroll(canceled: true), - excludeFromSemantics: true, - child: Stack( - children: [ - PostMountCallback( - key: primary.key, - callback: startAnimationCallback, - child: FadeTransition( - opacity: ReverseAnimation(opacity), - child: NotificationListener( - onNotification: (_) => _isTransitioning, - child: PositionedList( - itemBuilder: widget.itemBuilder, - separatorBuilder: widget.separatorBuilder, - itemCount: widget.itemCount, - positionedIndex: primary.target, - controller: primary.scrollController, - itemPositionsNotifier: primary.itemPositionsNotifier, - scrollDirection: widget.scrollDirection, - reverse: widget.reverse, - cacheExtent: cacheExtent, - alignment: primary.alignment, - physics: widget.physics, - addSemanticIndexes: widget.addSemanticIndexes, - semanticChildCount: widget.semanticChildCount, - padding: widget.padding, - addAutomaticKeepAlives: widget.addAutomaticKeepAlives, - addRepaintBoundaries: widget.addRepaintBoundaries, - findChildIndexCallback: widget.findChildIndexCallback, - ), - ), - ), - ), - if (_isTransitioning) + Widget build(BuildContext context) => LayoutBuilder( + builder: (context, constraints) { + final cacheExtent = _cacheExtent(constraints); + return GestureDetector( + onPanDown: (_) => _stopScroll(canceled: true), + excludeFromSemantics: true, + child: Stack( + children: [ PostMountCallback( - key: secondary.key, + key: primary.key, callback: startAnimationCallback, child: FadeTransition( - opacity: opacity, + opacity: ReverseAnimation(opacity), child: NotificationListener( - onNotification: (_) => false, + onNotification: (_) => _isTransitioning, child: PositionedList( itemBuilder: widget.itemBuilder, separatorBuilder: widget.separatorBuilder, itemCount: widget.itemCount, - itemPositionsNotifier: secondary.itemPositionsNotifier, - positionedIndex: secondary.target, - controller: secondary.scrollController, + positionedIndex: primary.target, + controller: primary.scrollController, + itemPositionsNotifier: primary.itemPositionsNotifier, scrollDirection: widget.scrollDirection, reverse: widget.reverse, cacheExtent: cacheExtent, - alignment: secondary.alignment, + alignment: primary.alignment, physics: widget.physics, addSemanticIndexes: widget.addSemanticIndexes, semanticChildCount: widget.semanticChildCount, padding: widget.padding, addAutomaticKeepAlives: widget.addAutomaticKeepAlives, addRepaintBoundaries: widget.addRepaintBoundaries, + findChildIndexCallback: widget.findChildIndexCallback, ), ), ), ), - ], - ), - ); - }, - ); - } + if (_isTransitioning) + PostMountCallback( + key: secondary.key, + callback: startAnimationCallback, + child: FadeTransition( + opacity: opacity, + child: NotificationListener( + onNotification: (_) => false, + child: PositionedList( + itemBuilder: widget.itemBuilder, + separatorBuilder: widget.separatorBuilder, + itemCount: widget.itemCount, + itemPositionsNotifier: + secondary.itemPositionsNotifier, + positionedIndex: secondary.target, + controller: secondary.scrollController, + scrollDirection: widget.scrollDirection, + reverse: widget.reverse, + cacheExtent: cacheExtent, + alignment: secondary.alignment, + physics: widget.physics, + addSemanticIndexes: widget.addSemanticIndexes, + semanticChildCount: widget.semanticChildCount, + padding: widget.padding, + addAutomaticKeepAlives: widget.addAutomaticKeepAlives, + addRepaintBoundaries: widget.addRepaintBoundaries, + ), + ), + ), + ), + ], + ), + ); + }, + ); double _cacheExtent(BoxConstraints constraints) => max( constraints.maxHeight * _screenScrollCount, @@ -419,8 +419,9 @@ class _ScrollablePositionedListState extends State } setState(() { primary.scrollController.jumpTo(0); - primary.target = index; - primary.alignment = alignment; + primary + ..target = index + ..alignment = alignment; }); } @@ -505,8 +506,9 @@ class _ScrollablePositionedListState extends State setState(() { // TODO: _startScroll can be re-entrant, which invalidates this assert. // assert(!_isTransitioning); - secondary.target = index; - secondary.alignment = alignment; + secondary + ..target = index + ..alignment = alignment; _isTransitioning = true; }); await Future.wait([startCompleter.future, endCompleter.future]); @@ -532,7 +534,7 @@ class _ScrollablePositionedListState extends State if (opacity.value >= 0.5) { // Secondary [ListView] is more visible than the primary; make it the // new primary. - var temp = primary; + final temp = primary; primary = secondary; secondary = temp; } @@ -542,8 +544,8 @@ class _ScrollablePositionedListState extends State } Animatable _opacityAnimation(List opacityAnimationWeights) { - final startOpacity = 0.0; - final endOpacity = 1.0; + const startOpacity = 0.0; + const endOpacity = 1.0; return TweenSequence(>[ TweenSequenceItem( tween: ConstantTween(startOpacity), diff --git a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/viewport.dart b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/viewport.dart index 1de5ff05..7e307040 100644 --- a/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/viewport.dart +++ b/packages/stream_chat_flutter/lib/src/scrollable_positioned_list/src/viewport.dart @@ -2,17 +2,22 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// ignore_for_file: lines_longer_than_80_chars + import 'dart:math' as math; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; +/// {@template unbounded_viewport} /// A render object that is bigger on the inside. /// /// Version of [Viewport] with some modifications to how extents are /// computed to allow scroll extents outside 0 to 1. See [Viewport] /// for more information. +/// description class UnboundedViewport extends Viewport { + /// {@macro unbounded_viewport} UnboundedViewport({ Key? key, AxisDirection axisDirection = AxisDirection.down, @@ -40,16 +45,15 @@ class UnboundedViewport extends Viewport { double get anchor => _anchor; @override - RenderViewport createRenderObject(BuildContext context) { - return UnboundedRenderViewport( - axisDirection: axisDirection, - crossAxisDirection: crossAxisDirection ?? - Viewport.getDefaultCrossAxisDirection(context, axisDirection), - anchor: anchor, - offset: offset, - cacheExtent: cacheExtent, - ); - } + RenderViewport createRenderObject(BuildContext context) => + UnboundedRenderViewport( + axisDirection: axisDirection, + crossAxisDirection: crossAxisDirection ?? + Viewport.getDefaultCrossAxisDirection(context, axisDirection), + anchor: anchor, + offset: offset, + cacheExtent: cacheExtent, + ); } /// A render object that is bigger on the inside. @@ -100,7 +104,6 @@ class UnboundedRenderViewport extends RenderViewport { @override set anchor(double value) { - assert(value != null); if (value == _anchor) return; _anchor = value; markNeedsLayout(); @@ -124,8 +127,6 @@ class UnboundedRenderViewport extends RenderViewport { @override Rect describeSemanticsClip(RenderSliver? child) { - assert(axis != null); - if (_calculatedCacheExtent == null) { return semanticBounds; } @@ -151,14 +152,14 @@ class UnboundedRenderViewport extends RenderViewport { @override void performLayout() { if (center == null) { - assert(firstChild == null); + assert(firstChild == null, 'firstChild cannot be null'); _minScrollExtent = 0.0; _maxScrollExtent = 0.0; _hasVisualOverflow = false; - offset.applyContentDimensions(0.0, 0.0); + offset.applyContentDimensions(0, 0); return; } - assert(center!.parent == this); + assert(center!.parent == this, 'center.parent cannot be equal to this'); late double mainAxisExtent; late double crossAxisExtent; @@ -178,7 +179,6 @@ class UnboundedRenderViewport extends RenderViewport { double correction; var count = 0; do { - assert(offset.pixels != null); correction = _attemptLayout(mainAxisExtent, crossAxisExtent, offset.pixels + centerOffsetAdjustment); if (correction != 0.0) { @@ -187,17 +187,18 @@ class UnboundedRenderViewport extends RenderViewport { // *** Difference from [RenderViewport]. final top = _minScrollExtent + mainAxisExtent * anchor; final bottom = _maxScrollExtent - mainAxisExtent * (1.0 - anchor); - final maxScrollOffset = math.max(math.min(0.0, top), bottom); - final minScrollOffset = math.min(top, maxScrollOffset); - if (offset.applyContentDimensions(minScrollOffset, maxScrollOffset)) + final maxScrollOffset = math.max(math.min(0, top), bottom); + final minScrollOffset = math.min(top, maxScrollOffset); + if (offset.applyContentDimensions(minScrollOffset, maxScrollOffset)) { break; + } // *** End of difference from [RenderViewport]. } count += 1; } while (count < _maxLayoutCycles); assert(() { if (count >= _maxLayoutCycles) { - assert(count != 1); + assert(count != 1, 'count not equal to 1'); throw FlutterError( 'A RenderViewport exceeded its maximum number of layout cycles.\n' 'RenderViewport render objects, during layout, can retry if either their ' @@ -217,16 +218,16 @@ class UnboundedRenderViewport extends RenderViewport { ' layout passes.'); } return true; - }()); + }(), 'count needs to be bigger than _maxLayoutCycles'); } double _attemptLayout( double mainAxisExtent, double crossAxisExtent, double correctedOffset) { - assert(!mainAxisExtent.isNaN); - assert(mainAxisExtent >= 0.0); - assert(crossAxisExtent.isFinite); - assert(crossAxisExtent >= 0.0); - assert(correctedOffset.isFinite); + assert(!mainAxisExtent.isNaN, 'assert mainAxisExtent.isNaN'); + assert(mainAxisExtent >= 0.0, 'assert mainAxisExtent >= 0.0'); + assert(crossAxisExtent.isFinite, 'assert crossAxisExtent.isFinite'); + assert(crossAxisExtent >= 0.0, 'assert crossAxisExtent >= 0.0'); + assert(correctedOffset.isFinite, 'assert correctedOffset.isFinite'); _minScrollExtent = 0.0; _maxScrollExtent = 0.0; _hasVisualOverflow = false; @@ -234,10 +235,10 @@ class UnboundedRenderViewport extends RenderViewport { // centerOffset is the offset from the leading edge of the RenderViewport // to the zero scroll offset (the line between the forward slivers and the // reverse slivers). - final double centerOffset = mainAxisExtent * anchor - correctedOffset; - final double reverseDirectionRemainingPaintExtent = + final centerOffset = mainAxisExtent * anchor - correctedOffset; + final reverseDirectionRemainingPaintExtent = centerOffset.clamp(0.0, mainAxisExtent); - final double forwardDirectionRemainingPaintExtent = + final forwardDirectionRemainingPaintExtent = (mainAxisExtent - centerOffset).clamp(0.0, mainAxisExtent); switch (cacheExtentStyle) { @@ -249,21 +250,21 @@ class UnboundedRenderViewport extends RenderViewport { break; } - final double fullCacheExtent = mainAxisExtent + 2 * _calculatedCacheExtent!; - final double centerCacheOffset = centerOffset + _calculatedCacheExtent!; - final double reverseDirectionRemainingCacheExtent = + final fullCacheExtent = mainAxisExtent + 2 * _calculatedCacheExtent!; + final centerCacheOffset = centerOffset + _calculatedCacheExtent!; + final reverseDirectionRemainingCacheExtent = centerCacheOffset.clamp(0.0, fullCacheExtent); - final double forwardDirectionRemainingCacheExtent = + final forwardDirectionRemainingCacheExtent = (fullCacheExtent - centerCacheOffset).clamp(0.0, fullCacheExtent); - final RenderSliver? leadingNegativeChild = childBefore(center!); + final leadingNegativeChild = childBefore(center!); if (leadingNegativeChild != null) { // negative scroll offsets - final double result = layoutChildSequence( + final result = layoutChildSequence( child: leadingNegativeChild, scrollOffset: math.max(mainAxisExtent, centerOffset) - mainAxisExtent, - overlap: 0.0, + overlap: 0, layoutOffset: forwardDirectionRemainingPaintExtent, remainingPaintExtent: reverseDirectionRemainingPaintExtent, mainAxisExtent: mainAxisExtent, @@ -280,9 +281,8 @@ class UnboundedRenderViewport extends RenderViewport { // positive scroll offsets return layoutChildSequence( child: center, - scrollOffset: math.max(0.0, -centerOffset), - overlap: - leadingNegativeChild == null ? math.min(0.0, -centerOffset) : 0.0, + scrollOffset: math.max(0, -centerOffset), + overlap: leadingNegativeChild == null ? math.min(0, -centerOffset) : 0.0, layoutOffset: centerOffset >= mainAxisExtent ? centerOffset : reverseDirectionRemainingPaintExtent, diff --git a/packages/stream_chat_flutter/test/src/scrollable_positioned_list/reversed_positioned_list_test.dart b/packages/stream_chat_flutter/test/src/scrollable_positioned_list/reversed_positioned_list_test.dart index 98979df1..8b3a1ab5 100644 --- a/packages/stream_chat_flutter/test/src/scrollable_positioned_list/reversed_positioned_list_test.dart +++ b/packages/stream_chat_flutter/test/src/scrollable_positioned_list/reversed_positioned_list_test.dart @@ -117,7 +117,7 @@ void main() { }); testWidgets('List positioned with 15 at bottom', (WidgetTester tester) async { - await setUpWidgetTest(tester, topItem: 15, anchor: 0); + await setUpWidgetTest(tester, topItem: 15); await tester.pump(); expect(find.text('Item 14'), findsNothing); diff --git a/packages/stream_chat_flutter/test/src/scrollable_positioned_list/scrollable_positioned_list_test.dart b/packages/stream_chat_flutter/test/src/scrollable_positioned_list/scrollable_positioned_list_test.dart index bfdfa762..243aeeb1 100644 --- a/packages/stream_chat_flutter/test/src/scrollable_positioned_list/scrollable_positioned_list_test.dart +++ b/packages/stream_chat_flutter/test/src/scrollable_positioned_list/scrollable_positioned_list_test.dart @@ -50,7 +50,8 @@ void main() { itemCount: itemCount, itemScrollController: itemScrollController, itemBuilder: (context, index) { - assert(index >= 0 && index <= itemCount - 1); + assert(index >= 0 && index <= itemCount - 1, + '''index needs to be bigger or equal to 0 and smallert than itemCount -1'''); return SizedBox( height: variableHeight ? (itemHeight + (index % 13) * 5) : itemHeight, @@ -256,7 +257,7 @@ void main() { initialAlignment: 0.5); unawaited(itemScrollController.scrollTo( - index: 16, duration: scrollDuration, alignment: 1.0)); + index: 16, duration: scrollDuration, alignment: 1)); await tester.pump(); await tester.pump(); await tester.pump(scrollDuration + scrollDurationTolerance); @@ -457,7 +458,7 @@ void main() { final itemScrollController = ItemScrollController(); await setUpWidgetTest(tester, itemScrollController: itemScrollController); - var fadeTransitionFinder = find.descendant( + final fadeTransitionFinder = find.descendant( of: find.byType(ScrollablePositionedList), matching: find.byType(FadeTransition)); @@ -687,7 +688,7 @@ void main() { itemScrollController: itemScrollController, itemPositionsListener: itemPositionsListener); - itemScrollController.jumpTo(index: 100, alignment: 1.0); + itemScrollController.jumpTo(index: 100, alignment: 1); await tester.pump(); await tester.pump(); await tester.pump(scrollDuration + scrollDurationTolerance); @@ -758,7 +759,7 @@ void main() { itemPositionsListener: itemPositionsListener); unawaited(itemScrollController.scrollTo( - index: 100, alignment: 1.0, duration: scrollDuration)); + index: 100, alignment: 1, duration: scrollDuration)); await tester.pump(); await tester.pump(); await tester.pump(scrollDuration + scrollDurationTolerance); @@ -1138,13 +1139,13 @@ void main() { expect(find.text('Item 100'), findsNothing); expect(find.text('Item 200'), findsNothing); - var itemFinder = find.text('Item 300'); + final itemFinder = find.text('Item 300'); expect(itemFinder, findsOneWidget); expect(tester.getTopLeft(itemFinder).dy, 0); }, skip: true); testWidgets( - 'Jump to 400 at bottom, manually scroll, scroll to 100 at bottom and back', + '''Jump to 400 at bottom, manually scroll, scroll to 100 at bottom and back''', (WidgetTester tester) async { final itemScrollController = ItemScrollController(); final itemPositionsListener = ItemPositionsListener.create(); @@ -1168,7 +1169,7 @@ void main() { index: 400, alignment: 1, duration: scrollDuration)); await tester.pumpAndSettle(); - var itemFinder = find.text('Item 399'); + final itemFinder = find.text('Item 399'); expect(itemFinder, findsOneWidget); expect(tester.getBottomLeft(itemFinder).dy, screenHeight); }); @@ -1537,7 +1538,7 @@ void main() { }); testWidgets('List can be keyed', (WidgetTester tester) async { - final key = ValueKey('key'); + const key = ValueKey('key'); await setUpWidgetTest(tester, key: key); @@ -1559,7 +1560,7 @@ void main() { home: PageView( children: [ KeyedSubtree( - key: PageStorageKey('key'), + key: const PageStorageKey('key'), child: ScrollablePositionedList.builder( itemCount: defaultItemCount, itemScrollController: itemScrollController, @@ -1570,7 +1571,7 @@ void main() { itemPositionsListener: itemPositionsListener, ), ), - Center( + const Center( child: Text('Test'), ) ], @@ -1616,7 +1617,7 @@ void main() { home: PageView( children: [ KeyedSubtree( - key: PageStorageKey('key'), + key: const PageStorageKey('key'), child: ScrollablePositionedList.builder( itemCount: defaultItemCount, itemScrollController: itemScrollController, @@ -1627,7 +1628,7 @@ void main() { itemPositionsListener: itemPositionsListener, ), ), - Center( + const Center( child: Text('Test'), ) ], @@ -1663,7 +1664,7 @@ void main() { }); testWidgets( - 'Maintain programmatic and user position (9 half way off top) in page view', + '''Maintain programmatic and user position (9 half way off top) in page view''', (WidgetTester tester) async { final itemPositionsListener = ItemPositionsListener.create(); final itemScrollController = ItemScrollController(); @@ -1677,7 +1678,7 @@ void main() { home: PageView( children: [ KeyedSubtree( - key: PageStorageKey('key'), + key: const PageStorageKey('key'), child: ScrollablePositionedList.builder( itemCount: defaultItemCount, itemScrollController: itemScrollController, @@ -1688,7 +1689,7 @@ void main() { itemPositionsListener: itemPositionsListener, ), ), - Center( + const Center( child: Text('Test'), ) ], @@ -1728,7 +1729,7 @@ void main() { (itemHeight / screenHeight) / 2); }); - testWidgets("List with no items", (WidgetTester tester) async { + testWidgets('List with no items', (WidgetTester tester) async { final itemScrollController = ItemScrollController(); await setUpWidgetTest(tester, itemScrollController: itemScrollController, itemCount: 0); @@ -1750,22 +1751,21 @@ void main() { MaterialApp( home: ValueListenableBuilder( valueListenable: itemCount, - builder: (context, itemCount, child) { - return ScrollablePositionedList.builder( - initialScrollIndex: min(100, itemCount), - initialAlignment: 0, - itemCount: itemCount, - itemScrollController: itemScrollController, - itemPositionsListener: itemPositionsListener, - itemBuilder: (context, index) { - assert(index >= 0 && index <= itemCount - 1); - return SizedBox( - height: itemHeight, - child: Text('Item $index'), - ); - }, - ); - }, + builder: (context, itemCount, child) => + ScrollablePositionedList.builder( + initialScrollIndex: min(100, itemCount), + itemCount: itemCount, + itemScrollController: itemScrollController, + itemPositionsListener: itemPositionsListener, + itemBuilder: (context, index) { + assert(index >= 0 && index <= itemCount - 1, + 'index not bigger than 0 and smaller than itemCount - 1'); + return SizedBox( + height: itemHeight, + child: Text('Item $index'), + ); + }, + ), ), ), ); @@ -1795,20 +1795,19 @@ void main() { MaterialApp( home: ValueListenableBuilder( valueListenable: itemCount, - builder: (context, itemCount, child) { - return ScrollablePositionedList.builder( - initialScrollIndex: min(100, itemCount - 1), - initialAlignment: 0, - itemCount: itemCount, - itemBuilder: (context, index) { - assert(index >= 0 && index <= itemCount - 1); - return SizedBox( - height: itemHeight, - child: Text('Item $index'), - ); - }, - ); - }, + builder: (context, itemCount, child) => + ScrollablePositionedList.builder( + initialScrollIndex: min(100, itemCount - 1), + itemCount: itemCount, + itemBuilder: (context, index) { + assert(index >= 0 && index <= itemCount - 1, + 'index not bigger than 0 and smaller than itemCount -1'); + return SizedBox( + height: itemHeight, + child: Text('Item $index'), + ); + }, + ), ), ), ); @@ -1835,19 +1834,19 @@ void main() { MaterialApp( home: ValueListenableBuilder( valueListenable: itemCount, - builder: (context, itemCount, child) { - return ScrollablePositionedList.builder( - initialScrollIndex: itemCount - 1, - itemCount: itemCount, - itemBuilder: (context, index) { - assert(index >= 0 && index <= itemCount - 1); - return SizedBox( - height: itemHeight, - child: Text('Item $index'), - ); - }, - ); - }, + builder: (context, itemCount, child) => + ScrollablePositionedList.builder( + initialScrollIndex: itemCount - 1, + itemCount: itemCount, + itemBuilder: (context, index) { + assert(index >= 0 && index <= itemCount - 1, + 'index not bigger than 0 and smaller than itemCount -1'); + return SizedBox( + height: itemHeight, + child: Text('Item $index'), + ); + }, + ), ), ), ); @@ -1948,7 +1947,6 @@ void main() { tester, itemCount: 2, initialAlignment: alignment, - initialIndex: 0, ); await tester.pumpAndSettle(); @@ -1960,35 +1958,31 @@ void main() { tester.binding.window.devicePixelRatioTestValue = 1.0; tester.binding.window.physicalSizeTestValue = const Size(screenWidth, screenHeight); - final key = ValueNotifier(ValueKey('key')); + final key = ValueNotifier(const ValueKey('key')); final itemScrollController = ItemScrollController(); await tester.pumpWidget( MaterialApp( home: ValueListenableBuilder( valueListenable: key, - builder: (context, key, child) { - return Container( - key: key, - child: ScrollablePositionedList.builder( - itemCount: 200, - itemScrollController: itemScrollController, - itemBuilder: (context, index) { - return SizedBox( - height: itemHeight, - child: Text('Item $index'), - ); - }, + builder: (context, key, child) => Container( + key: key, + child: ScrollablePositionedList.builder( + itemCount: 200, + itemScrollController: itemScrollController, + itemBuilder: (context, index) => SizedBox( + height: itemHeight, + child: Text('Item $index'), ), - ); - }, + ), + ), ), ), ); await tester.pumpAndSettle(); - key.value = ValueKey('newKey'); + key.value = const ValueKey('newKey'); await tester.pumpAndSettle(); unawaited( @@ -2003,9 +1997,9 @@ void main() { tester.binding.window.devicePixelRatioTestValue = 1.0; tester.binding.window.physicalSizeTestValue = const Size(screenWidth, screenHeight); - final outerKey = ValueNotifier(ValueKey('outerKey')); + final outerKey = ValueNotifier(const ValueKey('outerKey')); final innerKey = GlobalKey(); - final listKey = ValueNotifier(ValueKey(null)); + final listKey = ValueNotifier(const ValueKey(null)); final itemScrollController = ItemScrollController(); await tester.pumpWidget( @@ -2038,8 +2032,8 @@ void main() { await tester.pumpAndSettle(); - outerKey.value = ValueKey('newOuterKey'); - listKey.value = ValueKey('newListKey'); + outerKey.value = const ValueKey('newOuterKey'); + listKey.value = const ValueKey('newListKey'); await tester.pumpAndSettle(); unawaited( @@ -2053,33 +2047,29 @@ void main() { tester.binding.window.devicePixelRatioTestValue = 1.0; tester.binding.window.physicalSizeTestValue = const Size(screenWidth, screenHeight); - final key = ValueNotifier(ValueKey('key')); + final key = ValueNotifier(const ValueKey('key')); final itemScrollController = ItemScrollController(); await tester.pumpWidget( MaterialApp( home: ValueListenableBuilder( valueListenable: key, - builder: (context, key, child) { - return ScrollablePositionedList.builder( - key: key, - itemCount: 10, - itemScrollController: itemScrollController, - itemBuilder: (context, index) { - return SizedBox( - height: itemHeight, - child: Text('Item $index'), - ); - }, - ); - }, + builder: (context, key, child) => ScrollablePositionedList.builder( + key: key, + itemCount: 10, + itemScrollController: itemScrollController, + itemBuilder: (context, index) => SizedBox( + height: itemHeight, + child: Text('Item $index'), + ), + ), ), ), ); await tester.pumpAndSettle(); - key.value = ValueKey('newKey'); + key.value = const ValueKey('newKey'); await tester.pumpAndSettle(); }); @@ -2087,35 +2077,31 @@ void main() { tester.binding.window.devicePixelRatioTestValue = 1.0; tester.binding.window.physicalSizeTestValue = const Size(screenWidth, screenHeight); - final key = ValueNotifier(ValueKey('key')); + final key = ValueNotifier(const ValueKey('key')); final itemScrollController = ItemScrollController(); await tester.pumpWidget( MaterialApp( home: ValueListenableBuilder( valueListenable: key, - builder: (context, key, child) { - return Container( - key: key, - child: ScrollablePositionedList.builder( - itemCount: 100, - itemScrollController: itemScrollController, - itemBuilder: (context, index) { - return SizedBox( - height: itemHeight, - child: Text('Item $index'), - ); - }, + builder: (context, key, child) => Container( + key: key, + child: ScrollablePositionedList.builder( + itemCount: 100, + itemScrollController: itemScrollController, + itemBuilder: (context, index) => SizedBox( + height: itemHeight, + child: Text('Item $index'), ), - ); - }, + ), + ), ), ), ); await tester.pumpAndSettle(); - key.value = ValueKey('newKey'); + key.value = const ValueKey('newKey'); await tester.pumpAndSettle(); unawaited( @@ -2130,7 +2116,7 @@ void main() { tester.binding.window.devicePixelRatioTestValue = 1.0; tester.binding.window.physicalSizeTestValue = const Size(screenWidth, screenHeight); - final containerKey = ValueNotifier(ValueKey('key')); + final containerKey = ValueNotifier(const ValueKey('key')); final scrollKey = GlobalKey(); final itemScrollController = ItemScrollController(); @@ -2138,29 +2124,25 @@ void main() { MaterialApp( home: ValueListenableBuilder( valueListenable: containerKey, - builder: (context, key, child) { - return Container( - key: key, - child: ScrollablePositionedList.builder( - key: scrollKey, - itemCount: 100, - itemScrollController: itemScrollController, - itemBuilder: (context, index) { - return SizedBox( - height: itemHeight, - child: Text('Item $index'), - ); - }, + builder: (context, key, child) => Container( + key: key, + child: ScrollablePositionedList.builder( + key: scrollKey, + itemCount: 100, + itemScrollController: itemScrollController, + itemBuilder: (context, index) => SizedBox( + height: itemHeight, + child: Text('Item $index'), ), - ); - }, + ), + ), ), ), ); await tester.pumpAndSettle(); - containerKey.value = ValueKey('newKey'); + containerKey.value = const ValueKey('newKey'); await tester.pumpAndSettle(); unawaited( @@ -2184,18 +2166,15 @@ void main() { MaterialApp( home: ValueListenableBuilder( valueListenable: itemScrollControllerListenable, - builder: (context, itemScrollController, child) { - return ScrollablePositionedList.builder( - itemCount: 100, - itemScrollController: itemScrollController, - itemBuilder: (context, index) { - return SizedBox( - height: itemHeight, - child: Text('Item $index'), - ); - }, - ); - }, + builder: (context, itemScrollController, child) => + ScrollablePositionedList.builder( + itemCount: 100, + itemScrollController: itemScrollController, + itemBuilder: (context, index) => SizedBox( + height: itemHeight, + child: Text('Item $index'), + ), + ), ), ), ); @@ -2236,35 +2215,29 @@ void main() { Expanded( child: ValueListenableBuilder( valueListenable: topItemScrollControllerListenable, - builder: (context, itemScrollController, child) { - return ScrollablePositionedList.builder( - itemCount: 100, - itemScrollController: itemScrollController, - itemBuilder: (context, index) { - return SizedBox( - height: itemHeight, - child: Text('Item $index'), - ); - }, - ); - }, + builder: (context, itemScrollController, child) => + ScrollablePositionedList.builder( + itemCount: 100, + itemScrollController: itemScrollController, + itemBuilder: (context, index) => SizedBox( + height: itemHeight, + child: Text('Item $index'), + ), + ), ), ), Expanded( child: ValueListenableBuilder( valueListenable: bottomItemScrollControllerListenable, - builder: (context, itemScrollController, child) { - return ScrollablePositionedList.builder( - itemCount: 100, - itemScrollController: itemScrollController, - itemBuilder: (context, index) { - return SizedBox( - height: itemHeight, - child: Text('Item $index'), - ); - }, - ); - }, + builder: (context, itemScrollController, child) => + ScrollablePositionedList.builder( + itemCount: 100, + itemScrollController: itemScrollController, + itemBuilder: (context, index) => SizedBox( + height: itemHeight, + child: Text('Item $index'), + ), + ), ), ), ], diff --git a/packages/stream_chat_flutter/test/src/scrollable_positioned_list/separated_scrollable_positioned_list_test.dart b/packages/stream_chat_flutter/test/src/scrollable_positioned_list/separated_scrollable_positioned_list_test.dart index 3a052d0b..b0dac065 100644 --- a/packages/stream_chat_flutter/test/src/scrollable_positioned_list/separated_scrollable_positioned_list_test.dart +++ b/packages/stream_chat_flutter/test/src/scrollable_positioned_list/separated_scrollable_positioned_list_test.dart @@ -270,7 +270,7 @@ void main() { initialAlignment: 0.5); unawaited(itemScrollController.scrollTo( - index: 16, duration: scrollDuration, alignment: 1.0)); + index: 16, duration: scrollDuration, alignment: 1)); await tester.pump(); await tester.pump(); await tester.pump(scrollDuration + scrollDurationTolerance); @@ -477,7 +477,7 @@ void main() { }); testWidgets('List can be keyed', (WidgetTester tester) async { - final key = ValueKey('key'); + const key = ValueKey('key'); await setUpWidgetTest(tester, key: key); @@ -498,23 +498,20 @@ void main() { MaterialApp( home: ValueListenableBuilder( valueListenable: itemCount, - builder: (context, itemCount, child) { - return ScrollablePositionedList.separated( - initialScrollIndex: 0, - initialAlignment: 0, - itemCount: itemCount, - itemScrollController: itemScrollController, - itemPositionsListener: itemPositionsListener, - itemBuilder: (context, index) => SizedBox( - height: itemHeight, - child: Text('Item $index'), - ), - separatorBuilder: (context, index) => SizedBox( - height: separatorHeight, - child: Text('Separator $index'), - ), - ); - }, + builder: (context, itemCount, child) => + ScrollablePositionedList.separated( + itemCount: itemCount, + itemScrollController: itemScrollController, + itemPositionsListener: itemPositionsListener, + itemBuilder: (context, index) => SizedBox( + height: itemHeight, + child: Text('Item $index'), + ), + separatorBuilder: (context, index) => SizedBox( + height: separatorHeight, + child: Text('Separator $index'), + ), + ), ), ), ); @@ -542,23 +539,20 @@ void main() { MaterialApp( home: ValueListenableBuilder( valueListenable: itemCount, - builder: (context, itemCount, child) { - return ScrollablePositionedList.separated( - initialScrollIndex: 0, - initialAlignment: 0, - itemCount: itemCount, - itemScrollController: itemScrollController, - itemPositionsListener: itemPositionsListener, - itemBuilder: (context, index) => SizedBox( - height: itemHeight, - child: Text('Item $index'), - ), - separatorBuilder: (context, index) => SizedBox( - height: separatorHeight, - child: Text('Separator $index'), - ), - ); - }, + builder: (context, itemCount, child) => + ScrollablePositionedList.separated( + itemCount: itemCount, + itemScrollController: itemScrollController, + itemPositionsListener: itemPositionsListener, + itemBuilder: (context, index) => SizedBox( + height: itemHeight, + child: Text('Item $index'), + ), + separatorBuilder: (context, index) => SizedBox( + height: separatorHeight, + child: Text('Separator $index'), + ), + ), ), ), );