@@ -132,9 +132,17 @@ Future<void> _checkSequence(
132132 header: _Header (i, height: 20 ),
133133 child: _Item (i, height: 100 ))))));
134134
135- final extent = tester.getSize (find.byType (StickyHeaderListView )).onAxis (axis);
135+ final overallSize = tester.getSize (find.byType (StickyHeaderListView ));
136+ final extent = overallSize.onAxis (axis);
136137 assert (extent % 100 == 0 );
137138
139+ // A position `inset` from the center of the edge the header is found on.
140+ Offset headerInset (double inset) {
141+ return overallSize.center (Offset .zero)
142+ + offsetInDirection (axis.coordinateDirection,
143+ (extent / 2 - inset) * (headerAtCoordinateEnd ? 1 : - 1 ));
144+ }
145+
138146 final first = ! (reverse ^ reverseHeader);
139147
140148 final itemFinder = first ? find.byType (_Item ).first : find.byType (_Item ).last;
@@ -145,28 +153,39 @@ Future<void> _checkSequence(
145153 : tester.getBottomRight (finder).inDirection (axis.coordinateDirection);
146154 }
147155
148- void checkState () {
156+ Future <void > checkState () async {
157+ // Check the header comes from the expected item.
149158 final scrollOffset = controller.position.pixels;
150159 final expectedHeaderIndex = first
151160 ? (scrollOffset / 100 ).floor ()
152161 : (extent ~ / 100 - 1 ) + (scrollOffset / 100 ).ceil ();
153162 check (tester.widget <_Item >(itemFinder).index).equals (expectedHeaderIndex);
154163 check (_headerIndex (tester)).equals (expectedHeaderIndex);
155164
165+ // Check the layout of the header and item.
156166 final expectedItemInsetExtent =
157167 100 - (first ? scrollOffset % 100 : (- scrollOffset) % 100 );
168+ final double expectedHeaderInsetExtent =
169+ allowOverflow ? 20 : math.min (20 , expectedItemInsetExtent);
158170 check (insetExtent (itemFinder)).equals (expectedItemInsetExtent);
159- check (insetExtent (find.byType (_Header ))).equals (
160- allowOverflow ? 20 : math.min (20 , expectedItemInsetExtent));
171+ check (insetExtent (find.byType (_Header ))).equals (expectedHeaderInsetExtent);
172+
173+ // Check the header gets hit when it should, and not when it shouldn't.
174+ await tester.tapAt (headerInset (1 ));
175+ await tester.tapAt (headerInset (expectedHeaderInsetExtent - 1 ));
176+ check (_Header .takeTapCount ()).equals (2 );
177+ await tester.tapAt (headerInset (extent - 1 ));
178+ await tester.tapAt (headerInset (extent - (expectedHeaderInsetExtent - 1 )));
179+ check (_Header .takeTapCount ()).equals (0 );
161180 }
162181
163182 Future <void > jumpAndCheck (double position) async {
164183 controller.jumpTo (position);
165184 await tester.pump ();
166- checkState ();
185+ await checkState ();
167186 }
168187
169- checkState ();
188+ await checkState ();
170189 await jumpAndCheck (5 );
171190 await jumpAndCheck (10 );
172191 await jumpAndCheck (20 );
@@ -210,12 +229,21 @@ class _Header extends StatelessWidget {
210229 final int index;
211230 final double height;
212231
232+ static int takeTapCount () {
233+ final result = _tapCount;
234+ _tapCount = 0 ;
235+ return result;
236+ }
237+ static int _tapCount = 0 ;
238+
213239 @override
214240 Widget build (BuildContext context) {
215241 return SizedBox (
216242 height: height,
217243 width: height, // TODO clean up
218- child: Text ("Header $index " ));
244+ child: GestureDetector (
245+ onTap: () => _tapCount++ ,
246+ child: Text ("Header $index " )));
219247 }
220248}
221249
0 commit comments