Reputation: 85
I am trying to achieve the following layout
I tried using Stepper but it didn't really solved my issue so I tried using vanilla dart code itself
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Checkbox(value: true, onChanged: (value) {}),
Text("Complaint Received"),
],
),
Padding(
padding: const EdgeInsets.only(
left: 20,
),
child: Container(
padding: const EdgeInsets.all(0),
width: 2,
height: 80,
color: Colors.black,
),
),
Row(
children: <Widget>[
Checkbox(value: true, onChanged: (value) {}),
Text("Complaint Received"),
],
),
Container(
width: 2,
height: 10,
color: Colors.black,
),
Row(
children: <Widget>[
Checkbox(value: true, onChanged: (value) {}),
Text("Complaint Received"),
],
),
Container(
width: 2,
height: 10,
color: Colors.black,
),
Row(
children: <Widget>[
Checkbox(value: true, onChanged: (value) {}),
Text("Complaint Received"),
],
),
Container(
width: 2,
height: 10,
color: Colors.black,
),
],
),
Following is the ui which I achieved
I don't understand why there is padding between the first two row and the container
Upvotes: 2
Views: 1644
Reputation: 10334
In Flutter, Checkboxes are not pure widgets like the StatelessWidget
that we are used to.
Checkbox
draws its bounds, a box with rounded edges, and the 'check' mark itself through RenderObject
's paint
method, sort of like HTML5 Canvas (if you are familiar).
This fact makes it hard to customize Flutter checkboxes, even changing such trivial stuff like the padding around it.
My solution does not solve your problem in the way you tried to, but it does provide a great view just like the one you wanted to achieve.
final double barsHeight = 40.0;
final double barsWidth = 3.0;
final Color inactiveBarColor = Colors.grey;
final Color activeBarColor = Colors.blue;
Map<String, bool> steps = {
"Complaint Received": true,
"Engineer Assigned": true,
"Engineer On the way": false,
"Complaint Done": false,
};
@override
Widget build(BuildContext context) {
double rowPadding = (barsHeight - kRadialReactionRadius) / 2;
double _barHeight = barsHeight;
if (rowPadding < 0) {
rowPadding = 0;
_barHeight = kRadialReactionRadius;
}
return Padding(
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 16),
child: Stack(fit: StackFit.loose, children: <Widget>[
Positioned(
left: kRadialReactionRadius - barsWidth / 2,
top: kRadialReactionRadius + rowPadding,
bottom: kRadialReactionRadius + rowPadding,
width: barsWidth,
child: Column(mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, children: List.generate(steps.length - 1, (i) =>
Container(
margin: EdgeInsets.symmetric(vertical: kRadialReactionRadius / 2 - 2),
height: _barHeight + 4,
color: steps.values.elementAt(i) && steps.values.elementAt(i + 1) ? activeBarColor : inactiveBarColor,
)
))
),
Theme(
data: Theme.of(context).copyWith(disabledColor: inactiveBarColor, unselectedWidgetColor: inactiveBarColor),
child: Column(mainAxisSize: MainAxisSize.min, children: steps.keys.map((key) =>
Padding(
padding: EdgeInsets.symmetric(vertical: rowPadding),
child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: <Widget>[
Checkbox(
value: steps[key],
onChanged: steps[key] ? (_) {} : null,
activeColor: activeBarColor,
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
),
Text(key),
])
)
).toList())
)
]),
);
}
How it works, in short:
Checkbox
uses kRadialReactionRadius
constant for its size and padding. That's how we know its exact size and now we can draw our bars in-between each checkbox row.Column
with Checkboxes using Stack
.Theme
widget.To change checkbox state - simply modify values in steps
variable. e.g.
setState(() {
steps[steps.keys.elementAt(/*checkbox index*/)] = true;
});
Final result:
Let me know if this helped.
Upvotes: 4