Add support for reverse to ReorderableListView (#26203)
This commit is contained in:
parent
830c0dfe83
commit
8c5a41113e
@ -41,6 +41,7 @@ class _ListDemoState extends State<ReorderableListDemo> {
|
||||
|
||||
PersistentBottomSheetController<void> _bottomSheet;
|
||||
_ReorderableListType _itemType = _ReorderableListType.threeLine;
|
||||
bool _reverse = false;
|
||||
bool _reverseSort = false;
|
||||
final List<_ListItem> _items = <String>[
|
||||
'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
|
||||
@ -51,7 +52,21 @@ class _ListDemoState extends State<ReorderableListDemo> {
|
||||
_itemType = type;
|
||||
});
|
||||
// Rebuild the bottom sheet to reflect the selected list view.
|
||||
_bottomSheet?.setState(() { });
|
||||
_bottomSheet?.setState(() {
|
||||
// Trigger a rebuild.
|
||||
});
|
||||
// Close the bottom sheet to give the user a clear view of the list.
|
||||
_bottomSheet?.close();
|
||||
}
|
||||
|
||||
void changeReverse(bool newValue) {
|
||||
setState(() {
|
||||
_reverse = newValue;
|
||||
});
|
||||
// Rebuild the bottom sheet to reflect the selected list view.
|
||||
_bottomSheet?.setState(() {
|
||||
// Trigger a rebuild.
|
||||
});
|
||||
// Close the bottom sheet to give the user a clear view of the list.
|
||||
_bottomSheet?.close();
|
||||
}
|
||||
@ -67,6 +82,12 @@ class _ListDemoState extends State<ReorderableListDemo> {
|
||||
shrinkWrap: true,
|
||||
primary: false,
|
||||
children: <Widget>[
|
||||
CheckboxListTile(
|
||||
dense: true,
|
||||
title: const Text('Reverse'),
|
||||
value: _reverse,
|
||||
onChanged: changeReverse,
|
||||
),
|
||||
RadioListTile<_ReorderableListType>(
|
||||
dense: true,
|
||||
title: const Text('Horizontal Avatars'),
|
||||
@ -189,6 +210,7 @@ class _ListDemoState extends State<ReorderableListDemo> {
|
||||
child: Text('Header of the list', style: Theme.of(context).textTheme.headline))
|
||||
: null,
|
||||
onReorder: _onReorder,
|
||||
reverse: _reverse,
|
||||
scrollDirection: _itemType == _ReorderableListType.horizontalAvatar ? Axis.horizontal : Axis.vertical,
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
children: _items.map<Widget>(buildListTile).toList(),
|
||||
|
@ -59,6 +59,7 @@ class ReorderableListView extends StatefulWidget {
|
||||
@required this.onReorder,
|
||||
this.scrollDirection = Axis.vertical,
|
||||
this.padding,
|
||||
this.reverse = false,
|
||||
}): assert(scrollDirection != null),
|
||||
assert(onReorder != null),
|
||||
assert(children != null),
|
||||
@ -83,6 +84,20 @@ class ReorderableListView extends StatefulWidget {
|
||||
/// The amount of space by which to inset the [children].
|
||||
final EdgeInsets padding;
|
||||
|
||||
/// Whether the scroll view scrolls in the reading direction.
|
||||
///
|
||||
/// For example, if the reading direction is left-to-right and
|
||||
/// [scrollDirection] is [Axis.horizontal], then the scroll view scrolls from
|
||||
/// left to right when [reverse] is false and from right to left when
|
||||
/// [reverse] is true.
|
||||
///
|
||||
/// Similarly, if [scrollDirection] is [Axis.vertical], then the scroll view
|
||||
/// scrolls from top to bottom when [reverse] is false and from bottom to top
|
||||
/// when [reverse] is true.
|
||||
///
|
||||
/// Defaults to false.
|
||||
final bool reverse;
|
||||
|
||||
/// Called when a list child is dropped into a new position to shuffle the
|
||||
/// underlying list.
|
||||
///
|
||||
@ -122,6 +137,7 @@ class _ReorderableListViewState extends State<ReorderableListView> {
|
||||
scrollDirection: widget.scrollDirection,
|
||||
onReorder: widget.onReorder,
|
||||
padding: widget.padding,
|
||||
reverse: widget.reverse,
|
||||
);
|
||||
},
|
||||
);
|
||||
@ -146,6 +162,7 @@ class _ReorderableListContent extends StatefulWidget {
|
||||
@required this.scrollDirection,
|
||||
@required this.padding,
|
||||
@required this.onReorder,
|
||||
@required this.reverse,
|
||||
});
|
||||
|
||||
final Widget header;
|
||||
@ -153,6 +170,7 @@ class _ReorderableListContent extends StatefulWidget {
|
||||
final Axis scrollDirection;
|
||||
final EdgeInsets padding;
|
||||
final ReorderCallback onReorder;
|
||||
final bool reverse;
|
||||
|
||||
@override
|
||||
_ReorderableListContentState createState() => _ReorderableListContentState();
|
||||
@ -544,16 +562,25 @@ class _ReorderableListContentState extends State<_ReorderableListContent> with T
|
||||
);
|
||||
break;
|
||||
}
|
||||
wrappedChildren.add(_wrap(
|
||||
finalDropArea,
|
||||
widget.children.length,
|
||||
constraints),
|
||||
);
|
||||
if (widget.reverse) {
|
||||
wrappedChildren.insert(0, _wrap(
|
||||
finalDropArea,
|
||||
widget.children.length,
|
||||
constraints),
|
||||
);
|
||||
} else {
|
||||
wrappedChildren.add(_wrap(
|
||||
finalDropArea,
|
||||
widget.children.length,
|
||||
constraints),
|
||||
);
|
||||
}
|
||||
return SingleChildScrollView(
|
||||
scrollDirection: widget.scrollDirection,
|
||||
child: _buildContainerForScrollDirection(children: wrappedChildren),
|
||||
padding: widget.padding,
|
||||
controller: _scrollController,
|
||||
reverse: widget.reverse,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -900,6 +900,30 @@ void main() {
|
||||
|
||||
});
|
||||
|
||||
testWidgets('ReorderableListView can be reversed', (WidgetTester tester) async {
|
||||
final Widget reorderableListView = ReorderableListView(
|
||||
children: const <Widget>[
|
||||
SizedBox(
|
||||
key: Key('A'),
|
||||
child: Text('A'),
|
||||
),
|
||||
SizedBox(
|
||||
key: Key('B'),
|
||||
child: Text('B'),
|
||||
),
|
||||
SizedBox(
|
||||
key: Key('C'),
|
||||
child: Text('C'),
|
||||
)
|
||||
],
|
||||
reverse: true,
|
||||
onReorder: (int oldIndex, int newIndex) {},
|
||||
);
|
||||
await tester.pumpWidget(MaterialApp(
|
||||
home: reorderableListView,
|
||||
));
|
||||
expect(tester.getCenter(find.text('A')), greaterThan(tester.getCenter(find.text('B'))));
|
||||
});
|
||||
// TODO(djshuckerow): figure out how to write a test for scrolling the list.
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user