@@ -67,38 +67,38 @@ void main() {
6767
6868 for (final reverse in [true , false ]) {
6969 for (final reverseHeader in [true , false ]) {
70- for (final allowOverflow in [true , false ]) {
71- final name = 'sticky headers: '
72- 'scroll ${reverse ? 'up' : 'down' }, '
73- 'header at ${reverseHeader ? 'bottom' : 'top' }, '
74- 'headers ${allowOverflow ? 'overflow' : 'bounded' }' ;
75- testWidgets (name, (tester) =>
76- _checkSequence (tester,
77- Axis .vertical,
78- reverse: reverse,
79- reverseHeader: reverseHeader,
80- allowOverflow: allowOverflow,
81- ));
82- }
83- }
84- }
85-
86- for (final reverse in [true , false ]) {
87- for (final reverseHeader in [true , false ]) {
88- for (final allowOverflow in [true , false ]) {
89- for (final textDirection in TextDirection .values) {
70+ for (final growthDirection in GrowthDirection .values) {
71+ for (final allowOverflow in [true , false ]) {
9072 final name = 'sticky headers: '
91- '${ textDirection . name . toUpperCase ()} '
92- 'scroll ${ reverse ? 'backward ' : 'forward ' }, '
93- 'header at ${ reverseHeader ? 'end' : 'start' } , '
73+ 'scroll ${ reverse ? 'up' : 'down' }, '
74+ 'header at ${ reverseHeader ? 'bottom ' : 'top ' }, '
75+ '$ growthDirection , '
9476 'headers ${allowOverflow ? 'overflow' : 'bounded' }' ;
9577 testWidgets (name, (tester) =>
9678 _checkSequence (tester,
97- Axis .horizontal, textDirection : textDirection ,
79+ Axis .vertical ,
9880 reverse: reverse,
9981 reverseHeader: reverseHeader,
82+ growthDirection: growthDirection,
10083 allowOverflow: allowOverflow,
10184 ));
85+
86+ for (final textDirection in TextDirection .values) {
87+ final name = 'sticky headers: '
88+ '${textDirection .name .toUpperCase ()} '
89+ 'scroll ${reverse ? 'backward' : 'forward' }, '
90+ 'header at ${reverseHeader ? 'end' : 'start' }, '
91+ '$growthDirection , '
92+ 'headers ${allowOverflow ? 'overflow' : 'bounded' }' ;
93+ testWidgets (name, (tester) =>
94+ _checkSequence (tester,
95+ Axis .horizontal, textDirection: textDirection,
96+ reverse: reverse,
97+ reverseHeader: reverseHeader,
98+ growthDirection: growthDirection,
99+ allowOverflow: allowOverflow,
100+ ));
101+ }
102102 }
103103 }
104104 }
@@ -111,28 +111,43 @@ Future<void> _checkSequence(
111111 TextDirection ? textDirection,
112112 bool reverse = false ,
113113 bool reverseHeader = false ,
114+ GrowthDirection growthDirection = GrowthDirection .forward,
114115 required bool allowOverflow,
115116}) async {
116117 assert (textDirection != null || axis == Axis .vertical);
117118 final headerAtCoordinateEnd = switch (axis) {
118119 Axis .horizontal => reverseHeader ^ (textDirection == TextDirection .rtl),
119120 Axis .vertical => reverseHeader,
120121 };
122+ final reverseGrowth = (growthDirection == GrowthDirection .reverse);
121123
122124 final controller = ScrollController ();
125+ const listKey = ValueKey ("list" );
126+ const emptyKey = ValueKey ("empty" );
123127 await tester.pumpWidget (Directionality (
124128 textDirection: textDirection ?? TextDirection .rtl,
125- child: StickyHeaderListView (
129+ child: CustomScrollView (
126130 controller: controller,
127131 scrollDirection: axis,
128132 reverse: reverse,
129- reverseHeader: reverseHeader,
130- children: List .generate (100 , (i) => StickyHeaderItem (
131- allowOverflow: allowOverflow,
132- header: _Header (i, height: 20 ),
133- child: _Item (i, height: 100 ))))));
134-
135- final overallSize = tester.getSize (find.byType (StickyHeaderListView ));
133+ anchor: reverseGrowth ? 1.0 : 0.0 ,
134+ center: reverseGrowth ? emptyKey : listKey,
135+ slivers: [
136+ SliverStickyHeaderList (
137+ key: listKey,
138+ headerPlacement: (reverseHeader ^ reverse)
139+ ? HeaderPlacement .scrollingEnd : HeaderPlacement .scrollingStart,
140+ delegate: SliverChildListDelegate (
141+ List .generate (100 , (i) => StickyHeaderItem (
142+ allowOverflow: allowOverflow,
143+ header: _Header (i, height: 20 ),
144+ child: _Item (i, height: 100 ))))),
145+ const SliverPadding (
146+ key: emptyKey,
147+ padding: EdgeInsets .zero),
148+ ])));
149+
150+ final overallSize = tester.getSize (find.byType (CustomScrollView ));
136151 final extent = overallSize.onAxis (axis);
137152 assert (extent % 100 == 0 );
138153
@@ -143,7 +158,7 @@ Future<void> _checkSequence(
143158 (extent / 2 - inset) * (headerAtCoordinateEnd ? 1 : - 1 ));
144159 }
145160
146- final first = ! (reverse ^ reverseHeader);
161+ final first = ! (reverse ^ reverseHeader ^ reverseGrowth );
147162
148163 final itemFinder = first ? find.byType (_Item ).first : find.byType (_Item ).last;
149164
@@ -155,10 +170,11 @@ Future<void> _checkSequence(
155170
156171 Future <void > checkState () async {
157172 // Check the header comes from the expected item.
158- final scrollOffset = controller.position.pixels;
173+ final scrollOffset = controller.position.pixels * (reverseGrowth ? - 1 : 1 ) ;
159174 final expectedHeaderIndex = first
160175 ? (scrollOffset / 100 ).floor ()
161176 : (extent ~ / 100 - 1 ) + (scrollOffset / 100 ).ceil ();
177+ // print("$scrollOffset, $extent, $expectedHeaderIndex");
162178 check (tester.widget <_Item >(itemFinder).index).equals (expectedHeaderIndex);
163179 check (_headerIndex (tester)).equals (expectedHeaderIndex);
164180
@@ -180,7 +196,7 @@ Future<void> _checkSequence(
180196 }
181197
182198 Future <void > jumpAndCheck (double position) async {
183- controller.jumpTo (position);
199+ controller.jumpTo (position * (reverseGrowth ? - 1 : 1 ) );
184200 await tester.pump ();
185201 await checkState ();
186202 }
0 commit comments