@@ -132,9 +132,17 @@ Future<void> _checkSequence(
132
132
header: _Header (i, height: 20 ),
133
133
child: _Item (i, height: 100 ))))));
134
134
135
- final extent = tester.getSize (find.byType (StickyHeaderListView )).onAxis (axis);
135
+ final overallSize = tester.getSize (find.byType (StickyHeaderListView ));
136
+ final extent = overallSize.onAxis (axis);
136
137
assert (extent % 100 == 0 );
137
138
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
+
138
146
final first = ! (reverse ^ reverseHeader);
139
147
140
148
final itemFinder = first ? find.byType (_Item ).first : find.byType (_Item ).last;
@@ -145,28 +153,39 @@ Future<void> _checkSequence(
145
153
: tester.getBottomRight (finder).inDirection (axis.coordinateDirection);
146
154
}
147
155
148
- void checkState () {
156
+ Future <void > checkState () async {
157
+ // Check the header comes from the expected item.
149
158
final scrollOffset = controller.position.pixels;
150
159
final expectedHeaderIndex = first
151
160
? (scrollOffset / 100 ).floor ()
152
161
: (extent ~ / 100 - 1 ) + (scrollOffset / 100 ).ceil ();
153
162
check (tester.widget <_Item >(itemFinder).index).equals (expectedHeaderIndex);
154
163
check (_headerIndex (tester)).equals (expectedHeaderIndex);
155
164
165
+ // Check the layout of the header and item.
156
166
final expectedItemInsetExtent =
157
167
100 - (first ? scrollOffset % 100 : (- scrollOffset) % 100 );
168
+ final double expectedHeaderInsetExtent =
169
+ allowOverflow ? 20 : math.min (20 , expectedItemInsetExtent);
158
170
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 );
161
180
}
162
181
163
182
Future <void > jumpAndCheck (double position) async {
164
183
controller.jumpTo (position);
165
184
await tester.pump ();
166
- checkState ();
185
+ await checkState ();
167
186
}
168
187
169
- checkState ();
188
+ await checkState ();
170
189
await jumpAndCheck (5 );
171
190
await jumpAndCheck (10 );
172
191
await jumpAndCheck (20 );
@@ -210,12 +229,21 @@ class _Header extends StatelessWidget {
210
229
final int index;
211
230
final double height;
212
231
232
+ static int takeTapCount () {
233
+ final result = _tapCount;
234
+ _tapCount = 0 ;
235
+ return result;
236
+ }
237
+ static int _tapCount = 0 ;
238
+
213
239
@override
214
240
Widget build (BuildContext context) {
215
241
return SizedBox (
216
242
height: height,
217
243
width: height, // TODO clean up
218
- child: Text ("Header $index " ));
244
+ child: GestureDetector (
245
+ onTap: () => _tapCount++ ,
246
+ child: Text ("Header $index " )));
219
247
}
220
248
}
221
249
0 commit comments