Skip to content

Commit 5c44057

Browse files
authored
Apply indexToItemIndex to indices returned by findChildIndexCallback in SliverAnimatedListState (#108710)
1 parent bd0aafa commit 5c44057

File tree

2 files changed

+89
-1
lines changed

2 files changed

+89
-1
lines changed

packages/flutter/lib/src/widgets/animated_list.dart

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -514,7 +514,12 @@ class SliverAnimatedListState extends State<SliverAnimatedList> with TickerProvi
514514
return SliverChildBuilderDelegate(
515515
_itemBuilder,
516516
childCount: _itemsCount,
517-
findChildIndexCallback: widget.findChildIndexCallback,
517+
findChildIndexCallback: widget.findChildIndexCallback == null
518+
? null
519+
: (Key key) {
520+
final int? index = widget.findChildIndexCallback!(key);
521+
return index != null ? _indexToItemIndex(index) : null;
522+
},
518523
);
519524
}
520525

packages/flutter/test/widgets/animated_list_test.dart

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,67 @@ void main() {
357357
expect(find.text('removing'), findsNothing);
358358
expect(tester.getTopLeft(find.text('item 0')).dy, 200);
359359
});
360+
361+
testWidgets('passes correctly derived index of findChildIndexCallback to the inner SliverChildBuilderDelegate', (WidgetTester tester) async {
362+
final List<int> items = <int>[0, 1, 2, 3];
363+
final GlobalKey<SliverAnimatedListState> listKey = GlobalKey<SliverAnimatedListState>();
364+
365+
await tester.pumpWidget(
366+
Directionality(
367+
textDirection: TextDirection.ltr,
368+
child: CustomScrollView(
369+
slivers: <Widget>[
370+
SliverAnimatedList(
371+
key: listKey,
372+
initialItemCount: items.length,
373+
itemBuilder: (BuildContext context, int index, Animation<double> animation) {
374+
return _StatefulListItem(
375+
key: ValueKey<int>(items[index]),
376+
index: index,
377+
);
378+
},
379+
findChildIndexCallback: (Key key) {
380+
final int index = items.indexOf((key as ValueKey<int>).value);
381+
return index == -1 ? null : index;
382+
},
383+
),
384+
],
385+
),
386+
),
387+
);
388+
389+
// get all list entries in order
390+
final List<Text> listEntries = find.byType(Text).evaluate().map((Element e) => e.widget as Text).toList();
391+
392+
// check that the list is rendered in the correct order
393+
expect(listEntries[0].data, equals('item 0'));
394+
expect(listEntries[1].data, equals('item 1'));
395+
expect(listEntries[2].data, equals('item 2'));
396+
expect(listEntries[3].data, equals('item 3'));
397+
398+
399+
// delete one item
400+
listKey.currentState?.removeItem(0, (BuildContext context, Animation<double> animation) {
401+
return Container();
402+
});
403+
404+
// delete from list
405+
items.removeAt(0);
406+
407+
// reorder list
408+
items.insert(0, items.removeLast());
409+
410+
// render with new list order
411+
await tester.pumpAndSettle();
412+
413+
// get all list entries in order
414+
final List<Text> reorderedListEntries = find.byType(Text).evaluate().map((Element e) => e.widget as Text).toList();
415+
416+
// check that the stateful items of the list are rendered in the order provided by findChildIndexCallback
417+
expect(reorderedListEntries[0].data, equals('item 3'));
418+
expect(reorderedListEntries[1].data, equals('item 1'));
419+
expect(reorderedListEntries[2].data, equals('item 2'));
420+
});
360421
});
361422

362423
testWidgets(
@@ -428,3 +489,25 @@ void main() {
428489
expect(tester.widget<CustomScrollView>(find.byType(CustomScrollView)).clipBehavior, clipBehavior);
429490
});
430491
}
492+
493+
494+
class _StatefulListItem extends StatefulWidget {
495+
const _StatefulListItem({
496+
super.key,
497+
required this.index,
498+
});
499+
500+
final int index;
501+
502+
@override
503+
_StatefulListItemState createState() => _StatefulListItemState();
504+
}
505+
506+
class _StatefulListItemState extends State<_StatefulListItem> {
507+
late final int number = widget.index;
508+
509+
@override
510+
Widget build(BuildContext context) {
511+
return Text('item $number');
512+
}
513+
}

0 commit comments

Comments
 (0)