@@ -185,20 +185,58 @@ void main() {
185
185
});
186
186
187
187
testWidgets ('short/long -> scrolls to ends and no farther' , (tester) async {
188
- // Starts out scrolled to bottom.
188
+ // Starts out scrolled to top (to show top of the bottom sliver) .
189
189
await prepare (tester, topHeight: 100 , bottomHeight: 800 );
190
- check (tester.getRect (findBottom)).bottom.equals (600 );
190
+ check (tester.getRect (findTop)).top.equals (0 );
191
+ check (tester.getRect (findBottom)).bottom.equals (900 );
191
192
192
- // Try scrolling down (by dragging up ); doesn't move.
193
- await tester.drag (findBottom, Offset (0 , - 100 ));
193
+ // Try scrolling up (by dragging down ); doesn't move.
194
+ await tester.drag (findBottom, Offset (0 , 100 ));
194
195
await tester.pump ();
195
- check (tester.getRect (findBottom)).bottom.equals (600 );
196
+ check (tester.getRect (findBottom)).bottom.equals (900 );
196
197
197
- // Try scrolling up (by dragging down ); moves only as far as top of list.
198
- await tester.drag (findBottom, Offset (0 , 400 ));
198
+ // Try scrolling down (by dragging up ); moves only as far as bottom of list.
199
+ await tester.drag (findBottom, Offset (0 , - 400 ));
199
200
await tester.pump ();
200
- check (tester.getRect (findBottom)).bottom.equals (900 );
201
+ check (tester.getRect (findBottom)).bottom.equals (600 );
202
+ });
203
+
204
+ testWidgets ('starts by showing top of bottom sliver, long/long' , (tester) async {
205
+ // Both slivers are long; the bottom sliver gets 75% of the viewport.
206
+ await prepare (tester, topHeight: 1000 , bottomHeight: 3000 );
207
+ check (tester.getRect (findBottom)).top.equals (150 );
208
+ });
209
+
210
+ testWidgets ('starts by showing top of bottom sliver, short/long' , (tester) async {
211
+ // The top sliver is shorter than 25% of the viewport.
212
+ // It's shown in full, and the bottom sliver gets the rest (so >75%).
213
+ await prepare (tester, topHeight: 50 , bottomHeight: 3000 );
201
214
check (tester.getRect (findTop)).top.equals (0 );
215
+ check (tester.getRect (findBottom)).top.equals (50 );
216
+ });
217
+
218
+ testWidgets ('starts by showing top of bottom sliver, short/medium' , (tester) async {
219
+ // The whole list fits in the viewport. It's pinned to the bottom,
220
+ // even when that gives the bottom sliver more than 75%.
221
+ await prepare (tester, topHeight: 50 , bottomHeight: 500 );
222
+ check (tester.getRect (findTop))..top.equals (50 )..bottom.equals (100 );
223
+ check (tester.getRect (findBottom)).bottom.equals (600 );
224
+ });
225
+
226
+ testWidgets ('starts by showing top of bottom sliver, medium/short' , (tester) async {
227
+ // The whole list fits in the viewport. It's pinned to the bottom,
228
+ // even when that gives the top sliver more than 25%.
229
+ await prepare (tester, topHeight: 300 , bottomHeight: 100 );
230
+ check (tester.getRect (findTop))..top.equals (200 )..bottom.equals (500 );
231
+ check (tester.getRect (findBottom)).bottom.equals (600 );
232
+ });
233
+
234
+ testWidgets ('starts by showing top of bottom sliver, long/short' , (tester) async {
235
+ // The bottom sliver is shorter than 75% of the viewport.
236
+ // It's shown in full, and the top sliver gets the rest (so >25%).
237
+ await prepare (tester, topHeight: 1000 , bottomHeight: 300 );
238
+ check (tester.getRect (findTop)).bottom.equals (300 );
239
+ check (tester.getRect (findBottom)).bottom.equals (600 );
202
240
});
203
241
204
242
testWidgets ('short/short -> starts at bottom, immediately without animation' , (tester) async {
@@ -212,43 +250,46 @@ void main() {
212
250
check (ys).deepEquals (List .generate (10 , (_) => 0.0 ));
213
251
});
214
252
215
- testWidgets ('short/long -> starts at bottom , immediately without animation' , (tester) async {
253
+ testWidgets ('short/long -> starts at desired start , immediately without animation' , (tester) async {
216
254
await prepare (tester, topHeight: 100 , bottomHeight: 800 );
217
255
218
256
final ys = < double > [];
219
257
for (int i = 0 ; i < 10 ; i++ ) {
220
- ys.add (tester.getRect (findBottom).bottom - 600 );
258
+ ys.add (tester.getRect (findTop).top );
221
259
await tester.pump (Duration (milliseconds: 15 ));
222
260
}
223
261
check (ys).deepEquals (List .generate (10 , (_) => 0.0 ));
224
262
});
225
263
226
- testWidgets ('starts at bottom , even when bottom underestimated at first' , (tester) async {
264
+ testWidgets ('starts at desired start , even when bottom underestimated at first' , (tester) async {
227
265
const numItems = 10 ;
228
- const itemHeight = 300 .0 ;
266
+ const itemHeight = 20 .0 ;
229
267
230
268
// A list where the bottom sliver takes several rounds of layout
231
269
// to see how long it really is.
232
270
final controller = MessageListScrollController ();
233
271
await tester.pumpWidget (Directionality (textDirection: TextDirection .ltr,
234
272
child: MessageListScrollView (
235
273
controller: controller,
274
+ // The tiny cacheExtent causes each layout round to only reach
275
+ // the first item it expects will go beyond the viewport.
276
+ cacheExtent: 1.0 , // in (logical) pixels!
236
277
center: const ValueKey ('center' ),
237
278
slivers: [
238
279
SliverToBoxAdapter (
239
- child: SizedBox (height: 100 , child: Text ('top' ))),
280
+ child: SizedBox (height: 300 , child: Text ('top' ))),
240
281
SliverList .list (key: const ValueKey ('center' ),
241
282
children: List .generate (numItems, (i) =>
242
283
SizedBox (height: (i+ 1 ) * itemHeight, child: Text ('item $i ' )))),
243
284
])));
244
285
await tester.pump ();
245
286
246
- // Starts out scrolled all the way to the bottom,
247
- // even though it must have taken several rounds of layout to find that.
248
- check (controller.position.pixels)
249
- . equals (itemHeight * numItems * (numItems + 1 ) / 2 );
250
- check (tester. getRect (find. text ( 'item ${ numItems - 1 }' , skipOffstage : false )))
251
- .bottom. equals ( 600 );
287
+ // Starts out with the bottom sliver occupying 75% of the viewport…
288
+ check (controller.position.pixels). equals ( 450 );
289
+ // … even though it has more height than that.
290
+ check (tester. getRect (find. text ( 'item 6' ))).bottom. isGreaterThan ( 600 );
291
+ // (And even though on the first round of layout, it would have looked
292
+ // much shorter so that the view would have tried to scroll to its end.)
252
293
});
253
294
254
295
testWidgets ('stick to end of list when it grows' , (tester) async {
0 commit comments