Unverified Commit 83878683 authored by Kate Lovett's avatar Kate Lovett Committed by GitHub

Re-landing SliverAnimatedList (#42485)

parent 6db4c44d
......@@ -6,13 +6,67 @@ import 'package:flutter_test/flutter_test.dart';
import 'package:flutter/widgets.dart';
void main() {
testWidgets('AnimatedList initialItemCount', (WidgetTester tester) async {
final Map<int, Animation<double>> animations = <int, Animation<double>>{};
testWidgets('AnimatedList', (WidgetTester tester) async {
final AnimatedListItemBuilder builder = (BuildContext context, int index, Animation<double> animation) {
return SizedBox(
height: 100.0,
child: Center(
child: Text('item $index'),
),
);
};
final GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: AnimatedList(
key: listKey,
initialItemCount: 2,
itemBuilder: builder,
),
),
);
expect(find.byWidgetPredicate((Widget widget) {
return widget is SliverAnimatedList
&& widget.initialItemCount == 2
&& widget.itemBuilder == builder;
}), findsOneWidget);
listKey.currentState.insertItem(0);
await tester.pump();
expect(find.text('item 2'), findsOneWidget);
listKey.currentState.removeItem(
2,
(BuildContext context, Animation<double> animation) {
return const SizedBox(
height: 100.0,
child: Center(child: Text('removing item')),
);
},
duration: const Duration(milliseconds: 100),
);
await tester.pump();
expect(find.text('removing item'), findsOneWidget);
expect(find.text('item 2'), findsNothing);
await tester.pumpAndSettle(const Duration(milliseconds: 100));
expect(find.text('removing item'), findsNothing);
});
group('SliverAnimatedList', () {
testWidgets('initialItemCount', (WidgetTester tester) async {
final Map<int, Animation<double>> animations = <int, Animation<double>>{};
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: CustomScrollView(
slivers: <Widget>[
SliverAnimatedList(
initialItemCount: 2,
itemBuilder: (BuildContext context, int index, Animation<double> animation) {
animations[index] = animation;
......@@ -23,6 +77,8 @@ void main() {
),
);
},
)
],
),
),
);
......@@ -35,13 +91,15 @@ void main() {
expect(animations[1].value, 1.0);
});
testWidgets('AnimatedList insert', (WidgetTester tester) async {
final GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
testWidgets('insert', (WidgetTester tester) async {
final GlobalKey<SliverAnimatedListState> listKey = GlobalKey<SliverAnimatedListState>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: AnimatedList(
child: CustomScrollView(
slivers: <Widget>[
SliverAnimatedList(
key: listKey,
itemBuilder: (BuildContext context, int index, Animation<double> animation) {
return SizeTransition(
......@@ -50,12 +108,12 @@ void main() {
sizeFactor: animation,
child: SizedBox(
height: 100.0,
child: Center(
child: Text('item $index'),
),
child: Center(child: Text('item $index')),
),
);
},
)
],
),
),
);
......@@ -64,7 +122,10 @@ void main() {
double itemTop(int index) => tester.getTopLeft(find.byKey(ValueKey<int>(index), skipOffstage: false)).dy;
double itemBottom(int index) => tester.getBottomLeft(find.byKey(ValueKey<int>(index), skipOffstage: false)).dy;
listKey.currentState.insertItem(0, duration: const Duration(milliseconds: 100));
listKey.currentState.insertItem(
0,
duration: const Duration(milliseconds: 100),
);
await tester.pump();
// Newly inserted item 0's height should animate from 0 to 100
......@@ -79,11 +140,18 @@ void main() {
expect(itemTop(0), 0.0);
expect(itemBottom(0), 100.0);
listKey.currentState.insertItem(0, duration: const Duration(milliseconds: 100));
listKey.currentState.insertItem(0, duration: const Duration(milliseconds: 100));
listKey.currentState.insertItem(
0,
duration: const Duration(milliseconds: 100),
);
listKey.currentState.insertItem(
0,
duration: const Duration(milliseconds: 100),
);
await tester.pump();
// The height of the newly inserted items at index 0 and 1 should animate from 0 to 100.
// The height of the newly inserted items at index 0 and 1 should animate
// from 0 to 100.
// The height of the original item, now at index 2, should remain 100.
expect(itemHeight(0), 0.0);
expect(itemHeight(1), 0.0);
......@@ -109,8 +177,8 @@ void main() {
expect(itemBottom(2), 300.0);
});
testWidgets('AnimatedList remove', (WidgetTester tester) async {
final GlobalKey<AnimatedListState> listKey = GlobalKey<AnimatedListState>();
testWidgets('remove', (WidgetTester tester) async {
final GlobalKey<SliverAnimatedListState> listKey = GlobalKey<SliverAnimatedListState>();
final List<int> items = <int>[0, 1, 2];
Widget buildItem(BuildContext context, int item, Animation<double> animation) {
......@@ -130,12 +198,16 @@ void main() {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: AnimatedList(
child: CustomScrollView(
slivers: <Widget>[
SliverAnimatedList(
key: listKey,
initialItemCount: 3,
itemBuilder: (BuildContext context, int index, Animation<double> animation) {
return buildItem(context, items[index], animation);
},
)
],
),
),
);
......@@ -148,7 +220,8 @@ void main() {
expect(find.text('item 2'), findsOneWidget);
items.removeAt(0);
listKey.currentState.removeItem(0,
listKey.currentState.removeItem(
0,
(BuildContext context, Animation<double> animation) => buildItem(context, 0, animation),
duration: const Duration(milliseconds: 100),
);
......@@ -180,4 +253,70 @@ void main() {
expect(itemTop(2), 100.0);
expect(itemBottom(2), 200.0);
});
testWidgets('works in combination with other slivers', (WidgetTester tester) async {
final GlobalKey<SliverAnimatedListState> listKey = GlobalKey<SliverAnimatedListState>();
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
child: CustomScrollView(
slivers: <Widget>[
SliverList(
delegate: SliverChildListDelegate(<Widget>[
const SizedBox(height: 100),
const SizedBox(height: 100),
]),
),
SliverAnimatedList(
key: listKey,
initialItemCount: 3,
itemBuilder: (BuildContext context, int index, Animation<double> animation) {
return SizedBox(
height: 100,
child: Text('item $index'),
);
},
),
],
),
),
);
expect(tester.getTopLeft(find.text('item 0')).dy, 200);
expect(tester.getTopLeft(find.text('item 1')).dy, 300);
listKey.currentState.insertItem(3);
await tester.pumpAndSettle();
expect(tester.getTopLeft(find.text('item 3')).dy, 500);
listKey.currentState.removeItem(0,
(BuildContext context, Animation<double> animation) {
return SizeTransition(
sizeFactor: animation,
key: const ObjectKey('removing'),
child: const SizedBox(
height: 100,
child: Text('removing'),
),
);
},
duration: const Duration(seconds: 1),
);
await tester.pump();
expect(find.text('item 3'), findsNothing);
await tester.pump(const Duration(milliseconds: 500));
expect(
tester.getSize(find.byKey(const ObjectKey('removing'))).height,
50,
);
expect(tester.getTopLeft(find.text('item 0')).dy, 250);
await tester.pumpAndSettle();
expect(find.text('removing'), findsNothing);
expect(tester.getTopLeft(find.text('item 0')).dy, 200);
});
});
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment