mirror of
https://github.com/flutter/flutter
synced 2024-10-13 11:42:54 +00:00
Fixes issue, ReorderableListView destroys children even if their key-type wasn't changed (#64855)
This commit is contained in:
parent
38834d36d3
commit
011331dce5
|
@ -363,7 +363,7 @@ class _ReorderableListContentState extends State<_ReorderableListContent> with T
|
|||
// Handles up the logic for dragging and reordering items in the list.
|
||||
Widget _wrap(Widget toWrap, int index, BoxConstraints constraints) {
|
||||
assert(toWrap.key != null);
|
||||
final GlobalObjectKey keyIndexGlobalKey = GlobalObjectKey(toWrap.key);
|
||||
final _ReorderableListViewChildGlobalKey keyIndexGlobalKey = _ReorderableListViewChildGlobalKey(toWrap.key, this);
|
||||
// We pass the toWrapWithGlobalKey into the Draggable so that when a list
|
||||
// item gets dragged, the accessibility framework can preserve the selected
|
||||
// state of the dragging item.
|
||||
|
@ -596,3 +596,30 @@ class _ReorderableListContentState extends State<_ReorderableListContent> with T
|
|||
});
|
||||
}
|
||||
}
|
||||
|
||||
// A global key that takes its identity from the object and uses a value of a
|
||||
// particular type to identify itself.
|
||||
//
|
||||
// The difference with GlobalObjectKey is that it uses [==] instead of [identical]
|
||||
// of the objects used to generate widgets.
|
||||
@optionalTypeArgs
|
||||
class _ReorderableListViewChildGlobalKey extends GlobalObjectKey {
|
||||
|
||||
const _ReorderableListViewChildGlobalKey(this.subKey, this.state) : super(subKey);
|
||||
|
||||
final Key subKey;
|
||||
|
||||
final _ReorderableListContentState state;
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
if (other.runtimeType != runtimeType)
|
||||
return false;
|
||||
return other is _ReorderableListViewChildGlobalKey
|
||||
&& other.subKey == subKey
|
||||
&& other.state == state;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => hashValues(subKey, state);
|
||||
}
|
||||
|
|
|
@ -253,6 +253,35 @@ void main() {
|
|||
expect(findState(const Key('A')).checked, true);
|
||||
});
|
||||
|
||||
testWidgets('Preserves children states when rebuilt', (WidgetTester tester) async {
|
||||
const Key firstBox = Key('key');
|
||||
Widget build() {
|
||||
return MaterialApp(
|
||||
home: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: SizedBox(
|
||||
width: 100,
|
||||
height: 100,
|
||||
child: ReorderableListView(
|
||||
scrollDirection: Axis.vertical,
|
||||
children: const <Widget>[
|
||||
SizedBox(key: firstBox, width: 10, height: 10),
|
||||
],
|
||||
onReorder: (_, __) {},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// When the widget is rebuilt, the state of child should be consistent.
|
||||
await tester.pumpWidget(build());
|
||||
final Element e0 = tester.element(find.byKey(firstBox));
|
||||
await tester.pumpWidget(build());
|
||||
final Element e1 = tester.element(find.byKey(firstBox));
|
||||
expect(e0, equals(e1));
|
||||
});
|
||||
|
||||
testWidgets('Uses the PrimaryScrollController when available', (WidgetTester tester) async {
|
||||
final ScrollController primary = ScrollController();
|
||||
final Widget reorderableList = ReorderableListView(
|
||||
|
@ -771,6 +800,35 @@ void main() {
|
|||
expect(findState(const Key('A')).checked, true);
|
||||
});
|
||||
|
||||
testWidgets('Preserves children states when rebuilt', (WidgetTester tester) async {
|
||||
const Key firstBox = Key('key');
|
||||
Widget build() {
|
||||
return MaterialApp(
|
||||
home: Directionality(
|
||||
textDirection: TextDirection.ltr,
|
||||
child: SizedBox(
|
||||
width: 100,
|
||||
height: 100,
|
||||
child: ReorderableListView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
children: const <Widget>[
|
||||
SizedBox(key: firstBox, width: 10, height: 10),
|
||||
],
|
||||
onReorder: (_, __) {},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// When the widget is rebuilt, the state of child should be consistent.
|
||||
await tester.pumpWidget(build());
|
||||
final Element e0 = tester.element(find.byKey(firstBox));
|
||||
await tester.pumpWidget(build());
|
||||
final Element e1 = tester.element(find.byKey(firstBox));
|
||||
expect(e0, equals(e1));
|
||||
});
|
||||
|
||||
group('Accessibility (a11y/Semantics)', () {
|
||||
Map<CustomSemanticsAction, VoidCallback> getSemanticsActions(int index) {
|
||||
final Semantics semantics = find.ancestor(
|
||||
|
|
Loading…
Reference in a new issue