import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import '../../gallery/demo.dart';
enum _ReorderableListType {
/// A list tile that contains a [CircleAvatar].
horizontalAvatar,
/// A list tile that contains a [CircleAvatar].
verticalAvatar,
/// A list tile that contains three lines of text and a checkbox.
threeLine,
}
class ReorderableListDemo extends StatefulWidget {
const ReorderableListDemo({ Key key }) : super(key: key);
static const String routeName = '/material/reorderable-list';
@override
_ListDemoState createState() => _ListDemoState();
}
class _ListItem {
_ListItem(this.value, this.checkState);
final String value;
bool checkState;
}
class _ListDemoState extends State<ReorderableListDemo> {
static final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
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',
].map<_ListItem>((String item) => _ListItem(item, false)).toList();
void changeItemType(_ReorderableListType type) {
setState(() {
_itemType = type;
});
// 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();
}
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();
}
void _showConfigurationSheet() {
setState(() {
_bottomSheet = scaffoldKey.currentState.showBottomSheet<void>((BuildContext bottomSheetContext) {
return DecoratedBox(
decoration: const BoxDecoration(
border: Border(top: BorderSide(color: Colors.black26)),
),
child: ListView(
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'),
value: _ReorderableListType.horizontalAvatar,
groupValue: _itemType,
onChanged: changeItemType,
),
RadioListTile<_ReorderableListType>(
dense: true,
title: const Text('Vertical Avatars'),
value: _ReorderableListType.verticalAvatar,
groupValue: _itemType,
onChanged: changeItemType,
),
RadioListTile<_ReorderableListType>(
dense: true,
title: const Text('Three-line'),
value: _ReorderableListType.threeLine,
groupValue: _itemType,
onChanged: changeItemType,
),
],
),
);
});
// Garbage collect the bottom sheet when it closes.
_bottomSheet.closed.whenComplete(() {
if (mounted) {
setState(() {
_bottomSheet = null;
});
}
});
});
}
Widget buildListTile(_ListItem item) {
const Widget secondary = Text(
'Even more additional list item information appears on line three.',
);
Widget listTile;
switch (_itemType) {
case _ReorderableListType.threeLine:
listTile = CheckboxListTile(
key: Key(item.value),
isThreeLine: true,
value: item.checkState ?? false,
onChanged: (bool newValue) {
setState(() {
item.checkState = newValue;
});
},
title: Text('This item represents ${item.value}.'),
subtitle: secondary,
secondary: const Icon(Icons.drag_handle),
);
break;
case _ReorderableListType.horizontalAvatar:
case _ReorderableListType.verticalAvatar:
listTile = Container(
key: Key(item.value),
height: 100.0,
width: 100.0,
child: CircleAvatar(child: Text(item.value),
backgroundColor: Colors.green,
),
);
break;
}
return listTile;
}
void _onReorder(int oldIndex, int newIndex) {
setState(() {
if (newIndex > oldIndex) {
newIndex -= 1;
}
final _ListItem item = _items.removeAt(oldIndex);
_items.insert(newIndex, item);
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
key: scaffoldKey,
appBar: AppBar(
title: const Text('Reorderable list'),
actions: <Widget>[
MaterialDemoDocumentationButton(ReorderableListDemo.routeName),
IconButton(
icon: const Icon(Icons.sort_by_alpha),
tooltip: 'Sort',
onPressed: () {
setState(() {
_reverseSort = !_reverseSort;
_items.sort((_ListItem a, _ListItem b) => _reverseSort ? b.value.compareTo(a.value) : a.value.compareTo(b.value));
});
},
),
IconButton(
icon: Icon(
Theme.of(context).platform == TargetPlatform.iOS
? Icons.more_horiz
: Icons.more_vert,
),
tooltip: 'Show menu',
onPressed: _bottomSheet == null ? _showConfigurationSheet : null,
),
],
),
body: Scrollbar(
child: ReorderableListView(
header: _itemType != _ReorderableListType.threeLine
? Padding(
padding: const EdgeInsets.all(8.0),
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(),
),
),
);
}
}