I am trying to build a multiple choice Row from a list of Container widgets (wrapped in GestureDetector for onTap). When the user clicks on one of the Container widgets in the Row, that Container widget changes color (to blue) to reflect the user's selection. If the user then taps a different Container widget in the Row, THAT widget changes color to reflect the user's selection, and all others are reset to the initial color (white). Additionally, the user's choice (index?) must be retrievable.
All I have been able to do so far is create a Row of Container widgets that change color on tap, but function independently of one another. That is to say that the user may click on multiple selections, which is bad. I need some advice on how to break through to next level of functionality, where only one container may be selected and the selected value is passed-out.
Cheers, T
//choice button
class ChoiceButton extends StatefulWidget {
final String label;
final bool isPressed;
const ChoiceButton({
Key key,
this.isPressed = false,
this.label,
}) : super(key: key);
@override
_ChoiceButtonState createState() => _ChoiceButtonState();
}
class _ChoiceButtonState extends State<ChoiceButton> {
bool _isPressed;
@override
void initState() {
super.initState();
_isPressed = widget.isPressed;
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTap: () {
setState(() {
_isPressed = !_isPressed;
});
},
child: Container(
height: 80,
width: 80,
decoration: BoxDecoration(
color: _isPressed ? Colors.blue : Colors.transparent,
border: Border.all(
color: Colors.blue,
width: 80 * 0.05,
),
),
child: Center(
child: Text(
widget.label,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: _isPressed ? Colors.white : Colors.blue,
),
textAlign: TextAlign.center,
),
),
),
);
}
}
//choice row
class ChoiceRow extends StatefulWidget {
@override
_ChoiceRowState createState() => _ChoiceRowState();
}
class _ChoiceRowState extends State<ChoiceRow> {
bool isPressed = false;
String classChoice = '';
@override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: \[
SizedBox(width: 30),
ChoiceButton(
isPressed: isPressed,
label: 'A',
),
SizedBox(width: 10),
ChoiceButton(
isPressed: isPressed,
label: 'B',
),
SizedBox(width: 10),
ChoiceButton(
isPressed: isPressed,
label: 'C',
),
\],
);
}
}
I am providing two answers for this .... Use whichever one you prefer.
So Flutter provides a widget named ToggleButton which will satisfy all the needs mentioned above. Follow this documentation for more information about this widget.
You can add your custom ChoiceButton design in the widget list of the toggle button and with some tweak you will also be able to achieve your ChioceRow design too.
class ChoiceRow extends StatefulWidget {
@override
_ChoiceRowState createState() => _ChoiceRowState();
}
class _ChoiceRowState extends State<ChoiceRow> {
List<bool> isPressedList = [false,false,false];
String classChoice = '';
@override
Widget build(BuildContext context) {
print("Status L $isPressedList");
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
SizedBox(width: 30),
GestureDetector(
onTap: (){
print("Hello");
setState(() {
isPressedList[0] = true;
isPressedList[1] = false;
isPressedList[2] = false;
});
},
child: ChoiceButton(
isPressed: isPressedList[0],
label: 'A',
),
),
SizedBox(width: 10),
GestureDetector(
onTap: (){
setState(() {
isPressedList[0] = false;
isPressedList[1] = true;
isPressedList[2] = false;
});
},
child: ChoiceButton(
isPressed: isPressedList[1],
label: 'B',
),
),
SizedBox(width: 10),
GestureDetector(
onTap: (){
setState(() {
isPressedList[0] = false;
isPressedList[1] = false;
isPressedList[2] = true;
});
},
child: ChoiceButton(
isPressed: isPressedList[2],
label: 'C',
),
),
],
);
}
}
class ChoiceButton extends StatelessWidget {
final String label;
final bool isPressed;
ChoiceButton({this.label,this.isPressed});
@override
Widget build(BuildContext context) {
return Container(
height: 80,
width: 80,
decoration: BoxDecoration(
color: isPressed ? Colors.blue : Colors.transparent,
border: Border.all(
color: Colors.blue,
width: 80 * 0.05,
),
),
child: Center(
child: Text(
label,
style: TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
color: isPressed ? Colors.white : Colors.blue,
),
textAlign: TextAlign.center,
),
),
);
}
}
CHANGES :
I made a list (onPressedList) which keeps track of the current status of the toggle buttons (Like which is on and which others are off).
I moved the GestureDetector wrap on the button in the ChoiceRow class. This is because it will be difficult to pass the onTap result from ChoiceButton to ChoiceRow. (Now if you want the gesture detector in the Button class itself then you can make the list global or a static value in a completely different so that it can be properly accessed)
I made the ChoiceButton class Stateless as there is no need to keep it Stateful now.
The two things I did were adding a list that tracks the current status of the toggle buttons and when one toggle button is active all the others will be deactivated.
Now it is working as you mentioned above and you will also be able to keep track of the current status of all the buttons through "isPressedList".
GLHF :)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.