Reputation: 1474
I have a list created using ReorderableListView. I want to have a separate each list item with a Divider. I am looking for a clean solution, similar to ListView.separated(), however I can't find anything similar for ReorderableListView. In my code at the moment I am using a column widget to which I add a divider for every item but this is very "hacky". Do you know how this could be implemented in a better way?
I'm looking for divider like here:
My Code:
Main Page:
Widget _buildList(RoutinesState state) {
if (state is RoutinesFetched || state is RoutinesReordered) {
List<CustomCard> cards = [];
state.routines.forEach(
(e) {
cards.add(
CustomCard(
key: PageStorageKey(UniqueKey()),
title: e.name,
onTap: () {
Navigator.pushNamed(
context,
RoutineDetails.PAGE_ROUTE,
arguments: RoutineDetailsArgs(e),
);
},
includeDivider: cards.isNotEmpty,
),
);
},
);
return ReorderableListView(
children: cards,
onReorder: (int from, int to) => {
bloc.add(ReorderRoutine(fromIndex: from, toIndex: to)),
},
);
}
return Container(
child: Text("No routines found yet :( "),
);
}
Custom Card Widget:
@override
Widget build(BuildContext context) {
List<Widget> columnItems = [];
if (this.includeDivider) {
columnItems.add(Divider());
}
columnItems.add(ListTile(
leading: CircleAvatar(
child: Icon(Icons.fitness_center),
),
title: Text(this.title),
subtitle: Text("Weights"),
trailing: ActionChip(
label: Icon(Icons.play_arrow),
backgroundColor: Color(0xffECECEC),
onPressed: () => null,
),
onTap: this.onTap,
));
return Column(
mainAxisSize: MainAxisSize.min,
children: columnItems,
);
}
Upvotes: 8
Views: 3996
Reputation: 11
Have you attempted to decorate the container you are using with?
This suggestion by @J. S. worked for me like a charm. No need for a devider when you can just paint the bottom border.
First I tried it with Divider()
but that didn't look right because the ListTile is the "tappable" area and when you append a Divider below that, there is space that isn't considered tappable. So there is a white border above the divider that isn't painted with the splash effect. Also when you drag the Tile, it looked as if it would cut some of the lower tile with itself. This is what worked for me:
ReorderableListView.builder(
itemCount: _timeSegments!.length,
itemBuilder: (ctx, index) {
return Container(
key: Key(_timeSegments![index].id),
decoration: BoxDecoration(border: Border(bottom: BorderSide(color: Theme.of(context).dividerColor, width: 0.5))),
child: TimeSegmentTile(
timeSegment: _timeSegments![index],
press: () => Navigator.pushNamed(context, '/EditTimeSegmentScreen', arguments: EditTimeSegmentScreenArguments(_timeSegments![index], _timeSegmentRepository)),
),
);
},
onReorder: (int oldIndex, int newIndex) {
setState(() {
if (oldIndex < newIndex) {
newIndex -= 1;
}
final TimeSegment item = _timeSegments!.removeAt(oldIndex);
_timeSegments!.insert(newIndex, item);
});
},
),
Upvotes: 0
Reputation: 10519
You're right with using a Divider as it's usually used in ListTiles to serve as its name implies: a divider. Using a Column to define the Widgets in your ListTile isn't "hacky", you're just defining the Widgets in the ListTile the way it can be used. Also, since the Divider is added in the ListTile, when the tile is dragged, the Divider will be moved along with the entire ListTile as expected.
Upvotes: 2