flutter-expandable
flutter-expandable copied to clipboard
Expand one, collapse the other for ListView
how to use
I need like this.
I need like this too
I have some issue. Any advice?
Any update?
I need like this.
While there are no updates here, I finally figured out how to do it. Here's the workaround. Here's the sample code This is the parent widget
return ListView.builder(
itemCount: taskCardExpanded.length, // List<bool> taskCardExpanded = List.generate(3, (index) => false);
itemBuilder: (context, index) {
return Column(
children: [
TaskCard(
index: index,
isExpanded: taskCardExpanded[index],
onExpandedChanged: (isExpanded) { // to check if one of them expanded, and reset the others.
WidgetsBinding.instance.addPostFrameCallback((_) {
if (isExpanded) { // set current expanded value to true and reset the others
setState(() {
for (int i = 0; i < taskCardExpanded.length; i++) {
if (i == index) {
taskCardExpanded[i] = true;
} else {
taskCardExpanded[i] = false;
}
}
});
} else {
setState(() {
taskCardExpanded[index] = false;
});
}
});
},
),
const SizedBox(height: 10),
],
);
},
),
Here's the child code. I used the listener to tell the parent that the child changed it's value
class TaskCard extends StatefulWidget {
final bool isExpanded;
final void Function(bool isExpanded)? onExpandedChanged;
const TaskCard({
super.key,
this.isExpanded = false,
this.onExpandedChanged,
});
@override
State<TaskCard> createState() => _TaskCardState();
}
class _TaskCardState extends State<TaskCard> {
bool isExpanded = false;
late ExpandableController _controller;
@override
void initState() {
super.initState();
_controller = ExpandableController(initialExpanded: widget.isExpanded);
_controller.addListener(() {
setState(() {
isExpanded = !isExpanded;
});
widget.onExpandedChanged?.call(isExpanded);
});
}
@override
void didUpdateWidget(covariant TaskCard oldWidget) {
super.didUpdateWidget(oldWidget);
if (widget.isExpanded != isExpanded) {
_controller.toggle(); // the expansion/collapse happens cause of this
}
}
@override
Widget build(BuildContext context) {
return Material(
color: Colors.white,
clipBehavior: Clip.antiAliasWithSaveLayer,
borderRadius: BorderRadius.circular(15),
child: InkWell(
onTap: () => _controller.toggle(), // the expansion/collapse happens cause of this
child: Container(
padding: const EdgeInsets.symmetric(vertical: 5),
clipBehavior: Clip.antiAliasWithSaveLayer,
decoration: BoxDecoration(
color: Colors.transparent,
borderRadius: BorderRadius.circular(20),
border: Border.all(
width: isExpanded ? 1.3 : 1,
),
),
child: Padding(
padding: const EdgeInsets.fromLTRB(10, 0, 10, 10),
child: ExpandableNotifier(
controller: _controller,
child: ExpandablePanel(
theme: const ExpandableThemeData(
tapBodyToExpand: false,
hasIcon: false,
tapHeaderToExpand: false,
),
header: _buildHeader(),
collapsed: _buildCollapsed(),
expanded: _buildExpanded(),
),
),
),
),
),
);
}
}