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