This widget shows grouped data with expansion tile.
Set data and builder properties. data must be a class that extends GroupBase
. If you don't need additional property you can use GroupBase
class directly. The builder is assigned to title property of expansion tile.
class Category extends GroupBase {
String additional;
Category({
required this.additional,
required String uid,
String? parent,
}) : super(uid: uid, parent: parent);
}
List<Category> _createList() {
final topParents = List.generate(10,
(index) => Category(additional: "auto-generated-$index", uid: "2$index"));
return [
Category(additional: "group-1", uid: "1"),
Category(additional: "group-2", uid: "2"),
Category(additional: "group-1-1", uid: "3", parent: "1"),
Category(additional: "group-2-1", uid: "4", parent: "2"),
Category(additional: "group-3", uid: "5"),
Category(additional: "group-2-1-1", uid: "6", parent: "4"),
Category(additional: "group-2-2", uid: "7", parent: "2"),
Category(additional: "group-2-3", uid: "8", parent: "2"),
Category(additional: "group-2-1-1-1", uid: "9", parent: "6"),
Category(additional: "group-2-1-1-2", uid: "10", parent: "6"),
...topParents,
];
}
final groupedExpansionTile = GroupedExpansionTile<Category>(
data: _createList(),
builder: (parent, depth) => Text(parent.self.additional),
);
return Scaffold(
appBar: AppBar(
title: const Text("Simplest"),
),
body: groupedExpansionTile,
);
grouped-expansion-tile-sample-simple.mp4
You can make each item draggable. Set true to draggable
property to enable dragging. You can specify your own border to highlight the target widget when it will accept the dragged item. onAccept
is called when target item accepts dragged item. You can write your own process there for example to update the item list.
final List<Category> _data = _createList();
GroupedExpansionTile<Category>(
data: _data,
builder: (parent, depth) => Text(parent.self.additional),
childIndent: 50,
controlAffinity: ListTileControlAffinity.trailing,
initialBorder: Border.all(color: Colors.orange, width: 1),
highlightedBorder:
Border.all(color: Colors.deepPurple.shade800, width: 3),
initiallyExpanded: false,
draggable: true,
onAccept: (source, dest) async {
setState(() {
// source is one of elements of _data
source.self.parent = dest?.uid;
});
},
onExpansionChanged: (expanded, parent, depth) {
setState(() {
parent.self.additional += "@";
});
},
padding: EdgeInsets.zero,
);
grouped-expansion-tile-sample-advanced.mp4
- While dragging 3rd level item, top level item will accept the dragged item as long as dragged position is within the widget. It should accept the dragged item only while the dragged position is within collapsed parent area.