I'm using Flutter-Dart-SQLite to develop a quiz application. Here I have used RadioListTile for radio button functionality. I am passing the text value from an array to this StatefulWidget
.
This is the code I'm using,
import 'package:flutter/material.dart';
import 'package:get/get_state_manager/get_state_manager.dart';
import 'package:loginform_validation_demo/QuizApp/controllers/question_controller.dart';
import 'package:loginform_validation_demo/resource-file/constants.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter/src/material/radio_list_tile.dart';
class OptionRadio extends StatefulWidget {
final String text;
final int index;
final VoidCallback press;
const OptionRadio({
Key key,
this.text,
this.index,
this.press,
}) : super();
@override
OptionRadioPage createState() =>
OptionRadioPage(this.text, this.index, this.press);
}
class OptionRadioPage extends State<OptionRadio> {
final String text;
int index;
final VoidCallback press;
QuestionController controllerCopy =QuestionController();
int id = 1;
int selectedButton = null;
bool _isButtonDisabled;
OptionRadioPage(this.text, this.index, this.press);
@override
void initState() {
_isButtonDisabled = false;
}
int _selected = null;
@override
Widget build(BuildContext context) {
return GetBuilder<QuestionController>(
init: QuestionController(),
builder: (qnController) {
Color getTheRightColor() {
if (qnController.isAnswered) {
if (index == qnController.selectedAns &&
qnController.selectedAns == qnController.correctAns) {
return kBlackColor;
} else if (index == qnController.selectedAns &&
qnController.selectedAns != qnController.correctAns) {
return kBlackColor;
}
}
return kBlackColor;
}
return InkWell(
onTap: press,
child: Container(
child: Row(
children: <Widget>[
Expanded(
child: Container(
// height: 60.0,
child: Theme(
data: Theme.of(context).copyWith(
unselectedWidgetColor: Colors.grey,
disabledColor: Colors.blue),
child: Column(children:
[
RadioListTile(
title: Text(
"${index 1}. $text",
style: TextStyle(
color: getTheRightColor(), fontSize: 16),
softWrap: true,
),
/*Here the selectedButton which is null initially takes place of value after onChanged. Now, I need to clear the selected button when other button is clicked */
groupValue: selectedButton,
value: index,
activeColor: Colors.green,
onChanged:
(val) async {
debugPrint(
'Radio button is clicked onChanged $val');
setState(() {
debugPrint('Radio button setState $val');
selectedButton = val;
debugPrint('Radio button is clicked onChanged $index');
});
SharedPreferences prefs = await SharedPreferences.getInstance();
prefs.setInt('intValue', val);
},
toggleable: true,
),
]
),
)),
),
],
),
),
);
});
}
@override
State<StatefulWidget> createState() {
throw UnimplementedError();
}
}
Here the selectedButton which is null initially takes place of value of group value after onChanged
. Now, I need to clear the selected button when the other button is clicked.
I'm guessing I have something done wrong in group value part.
CodePudding user response:
Here is sample code by using your 'OptionRadioPage' Widget.
(but some code deleted because of leak of code)
As I commented, 'groupValue' should shared with two 'OptionRadioPage' widgets.
So I store that value 'OptionRadioPage' parent widget and
also pass the that value to 'OptionRadioPage' widgets.
import 'package:flutter/material.dart';
import 'package:flutter/src/material/radio_list_tile.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: Main(),
);
}
}
class Main extends StatefulWidget {
Main({Key key}) : super(key: key);
@override
_MainState createState() => _MainState();
}
class _MainState extends State<Main> {
int selectedButton;
@override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
OptionRadio(
text: 'Male',
index: 0,
selectedButton: selectedButton,
press: (val) {
selectedButton = val;
setState(() {});
}),
OptionRadio(
text: 'Female',
index: 1,
selectedButton: selectedButton,
press: (val) {
selectedButton = val;
setState(() {});
}),
],
),
),
);
}
}
class OptionRadio extends StatefulWidget {
final String text;
final int index;
final int selectedButton;
final Function press;
const OptionRadio({
Key key,
this.text,
this.index,
this.selectedButton,
this.press,
}) : super();
@override
OptionRadioPage createState() => OptionRadioPage();
}
class OptionRadioPage extends State<OptionRadio> {
// QuestionController controllerCopy =QuestionController();
int id = 1;
bool _isButtonDisabled;
OptionRadioPage();
@override
void initState() {
_isButtonDisabled = false;
}
int _selected = null;
@override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
widget.press(widget.index);
},
child: Container(
child: Row(
children: <Widget>[
Expanded(
child: Container(
// height: 60.0,
child: Theme(
data: Theme.of(context).copyWith(
unselectedWidgetColor: Colors.grey,
disabledColor: Colors.blue),
child: Column(children: [
RadioListTile(
title: Text(
"${widget.index 1}. ${widget.text}",
style: TextStyle(color: Colors.black, fontSize: 16),
softWrap: true,
),
/*Here the selectedButton which is null initially takes place of value after onChanged. Now, I need to clear the selected button when other button is clicked */
groupValue: widget.selectedButton,
value: widget.index,
activeColor: Colors.green,
onChanged: (val) async {
debugPrint('Radio button is clicked onChanged $val');
// setState(() {
// debugPrint('Radio button setState $val');
// selectedButton = val;
// debugPrint('Radio button is clicked onChanged $widget.index');
// });
// SharedPreferences prefs = await SharedPreferences.getInstance();
// prefs.setInt('intValue', val);
widget.press(widget.index);
},
toggleable: true,
),
]),
)),
),
],
),
),
);
}
}
CodePudding user response:
This is happening because you are defining individual groupValue
for each Radio button. Rather than defining selectedButton
field for each button define it once in that file where you are calling this widget
and pass the value
through it's constructor
like below code :
class OptionRadio extends StatefulWidget {
final String text;
final int index;
final ValueChanged<Object> press;
final int selectButton;
const OptionRadio({
Key key,
this.text,
this.index,
this.press,
this.selectButton,
}) : super();
@override
OptionRadioPage createState() =>
OptionRadioPage(this.text, this.index, this.press);
}
and use this value
and press
function to your Radio button like this :
RadioListTile(
title: Text(
"${index 1}. $text",
style: TextStyle(
color: Colors.green, fontSize: 16),
softWrap: true,
),
groupValue: widget.selectButton,
value: index,
activeColor: Colors.green,
onChanged: widget.press,
)
also pass ValueChanged(Object)
in place of VoidCallBack
:
final ValueChanged<Object> press;
and pass a proper function there like :
OptionRadio(
text: "abc",
index: index,
press: (val) => setState(() {
selectButton = int.parse(val.toString());
print("$selectButton");
}),
selectButton: selectButton,
)