how to make unselected color using radiotiles - flutter

I know that I can wrap my radio widgets with theme widget but in my case, i use different ways. how to make my radio button have a grey background color when on unselected?
#override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
RadioListTile<SingingCharacter>(
title: const Text('Akaun Individu', style: TextStyle(fontWeight: FontWeight.bold),),
subtitle: Text('Membuat pembayaran untuk diri sendiri'),
controlAffinity: ListTileControlAffinity.trailing,
value: SingingCharacter.akaunSendiri,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
Divider(thickness: 2),
RadioListTile<SingingCharacter>(
title: const Text('Akaun Syarikat', style: TextStyle(fontWeight: FontWeight.bold),),
subtitle: Text('Membuat pembayaran untuk organisasi'),
controlAffinity: ListTileControlAffinity.trailing,
value: SingingCharacter.akaunSyarikat,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
],
);
}
}

You can do this with overriding theme data.
Example:
...
body: Center(
child: Theme(
data: Theme.of(context).copyWith(
unselectedWidgetColor: Colors.purple,
),
child: Column(
children: [
RadioListTile<String>(
title: const Text(
'RadioListTile 1',
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: const Text('Selected'),
controlAffinity: ListTileControlAffinity.trailing,
value: 'value',
groupValue: 'value',
onChanged: (String? value) {},
),
RadioListTile<String>(
title: const Text(
'RadioListTile 2',
style: TextStyle(fontWeight: FontWeight.bold),
),
subtitle: const Text('Unselected'),
controlAffinity: ListTileControlAffinity.trailing,
value: 'value',
groupValue: 'valuex',
onChanged: (String? value) {},
),
],
),
),
),
...

add this property to your tile tileColor: varUnselect ? Colors.grey : Colors.transparent, varUnselect is get value of unselect radio

Related

flutter: Right overflowed by pixels

Here is my code:
return Scaffold(
appBar: AppBar(
backgroundColor: Colors.grey[900],
leading: IconButton(
icon: const Icon(Icons.arrow_back),
onPressed: () => Navigator.of(context).pop(false),
),
),
backgroundColor: Colors.grey[900],
body: Visibility(
visible: questionLoaded,
child: Builder(builder: (context) {
return Wrap(
spacing: 8.0,
runSpacing: 4.0,
direction: Axis.horizontal,
children: [
Container(
width: double.infinity,
child: Text(
question!.question,
textAlign: TextAlign.center,
style: GoogleFonts.mukta(
textStyle: TextStyle(
color: Colors.amber,
fontSize: 24,
shadows: const [
Shadow(
color: Colors.white,
offset: Offset.zero,
blurRadius: 15)
]),
),
),
),
if (question?.answer1 != "")
RadioButton(
textStyle: TextStyle(color: Colors.white),
description: (question?.answer1)!,
value: "1",
groupValue: _decision,
onChanged: (value) => setState(
() => _decision = value!,
),
),
if (question?.answer2 != "")
RadioButton(
textStyle: TextStyle(color: Colors.white),
description: (question?.answer2)!,
value: "2",
groupValue: _decision,
onChanged: (value) => setState(
() => _decision = value!,
),
),
if (question?.answer3 != "")
RadioButton(
textStyle: TextStyle(color: Colors.white),
description: (question?.answer3)!,
value: "3",
groupValue: _decision,
onChanged: (value) => setState(
() => _decision = value!,
),
),
if (question?.answer4 != "")
RadioButton(
textStyle: TextStyle(color: Colors.white),
description: (question?.answer4)!,
value: "4",
groupValue: _decision,
onChanged: (value) => setState(
() => _decision = value!,
),
),
],
);
})),
);
This produces the following issue:
Any idea why and how can I fix it ?
Wrap your Text widget Flexible or Expanded widget.
Expnaded( child: Text( question!.question,....
If your text is wrapped in column then column should be wrapped expanded widget.
Expanded(
child: Column(
children: [
Text(
'datadatadatadatadatadata',
overflow: TextOverflow.ellipsis,
)
],
),
),
But if your text is wrapped in a row then your text should be wrapped expanded widget.
Row(
children: [
Expanded(
child: Text(
'datadatadatadatadatadata',
overflow: TextOverflow.ellipsis,
),
)
],
),

Call a Widget based on the result of an If statement Flutter

I want to be able to call either one of two different widgets based on the result of an if statement.
I am able to get a Text Widget to show two different answers based on the result of the first dropdown box, but I am not able to call another widget the same way ...
import 'package:flutter/material.dart';
class FilterPage extends StatefulWidget {
const FilterPage({Key? key}) : super(key: key);
#override
State<FilterPage> createState() => _FilterPageState();
}
class _FilterPageState extends State<FilterPage> {
String firstDropdownValue = 'Option A';
String secondDropdownValue = 'Option B';
#override
void dispose() {
super.dispose();
}
static const String _title = 'Filter Code Sample';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
Padding(
padding: EdgeInsets.all(4),
),
],
title: Column(
children: [
Text(
'Filter',
style: TextStyle(fontSize: 22, color: Colors.amberAccent),
),
],
),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text(
'What are the Options ?',
style: TextStyle(fontSize: 16, color: Colors.white),
),
/*
* This is the first dropdown that is called, This dropdown provides
* two possible options,
* */
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: firstDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
firstDropdownValue = newValue!;
});
},
items: <String>['Option A', 'Option B']
.map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
/*
* So this is the if Statement that works based upon the first
* drop down box's answer...
*
* The problem is I can not get the system to call another Drop down Butten
* Widget based on the answer of the first DropdownBox,
* However, i can get a Text Widget to print...
* */
Text((() {
if (firstDropdownValue == 'Option A') {
return "Option is Option A";
}
return "Option is Option B";
})()),
/*
* This is the second dropbox that I would like to be called if the
* previous statement is met instead of the Text Widget above...
*(DROPBOX 2)
* */
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: secondDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
secondDropdownValue = newValue!;
});
},
items: <String>[
'Option 1',
'Option 2',
'Option 3',
].map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
/*
* This is also drop box two, but this dropbox with these different
* options should be called when the if statement is not met ..
*(DROPBOX 2)
* */
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: secondDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
secondDropdownValue = newValue!;
});
},
items: <String>[
'Option 4',
'Option 5',
'Option 6',
].map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
],
),
),
),
);
}
}
The flow diagram is maybe easier to get the whole picture from.
You can use a if(condition)...[widgetA] else...[WidgetB] structure:
class _FilterPageState extends State<FilterPage> {
String firstDropdownValue = 'Option A';
String secondDropdownValue = 'Option B';
#override
void dispose() {
super.dispose();
}
static const String _title = 'Filter Code Sample';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
Padding(
padding: EdgeInsets.all(4),
),
],
title: Column(
children: [
Text(
'Filter',
style: TextStyle(fontSize: 22, color: Colors.amberAccent),
),
],
),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text(
'What are the Options ?',
style: TextStyle(fontSize: 16, color: Colors.white),
),
/*
* This is the first dropdown that is called, This dropdown provides
* two possible options,
* */
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: firstDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
firstDropdownValue = newValue!;
});
},
items: <String>['Option A', 'Option B']
.map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
if(firstDropDownValue)...[
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: secondDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
secondDropdownValue = newValue!;
});
},
items: <String>[
'Option 1',
'Option 2',
'Option 3',
].map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
] else ...[
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: secondDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
secondDropdownValue = newValue!;
});
},
items: <String>[
'Option 4',
'Option 5',
'Option 6',
].map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
]
],
),
),
),
);
}
}
Not the best approach for this probably, but you can use a Builder widget, inside it put your if statement and if you don't want to show your widget there, return SizedBox.shrink() instead (don't forget to setState((){}) so that the widget containing them both rebuilds them. But a better answer may be using Bloc or some other state management package. Or even ValueNotifiers and ValueListenableBuilders to update your UI only where it's needed.
One solution here is to use an inline if condition like this:
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: firstDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
firstDropdownValue = newValue!;
});
},
items: <String>['Option A', 'Option B']
.map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
firstDropdownValue == 'Option A'?
DropdownButton(/*first dropdown*/) :
DropdownButton(/*second dropdown*/),
The other is creating a Widget variable at the beginning of the build method and giving it a value before returning the Scaffold, then put the created variable as one of the Column children:
#override
Widget build(BuildContext context) {
Widget bottomDropdown;
if (firstDropdownValue == 'Option A'){
bottomDropdown = DropdownButton(/*first dropdown*/);
} else {
bottomDropdown = DropdownButton(/*second dropdown*/);
}
return Scaffold(
appBar: AppBar(
//...other code
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: firstDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
firstDropdownValue = newValue!;
});
},
items: <String>['Option A', 'Option B']
.map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
bottomDropdown,
You can use the Dart short if form: if ? then : else.
Since the only thing that changes are the dropdown options, you can dynamically change them without the need to use another widget.
import 'package:flutter/material.dart';
class FilterPage extends StatefulWidget {
const FilterPage({Key? key}) : super(key: key);
#override
State<FilterPage> createState() => _FilterPageState();
}
class _FilterPageState extends State<FilterPage> {
String firstDropdownValue = '';
String secondDropdownValue = 'Option B';
#override
void dispose() {
super.dispose();
}
static const String _title = 'Filter Code Sample';
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
actions: [
Padding(
padding: EdgeInsets.all(4),
),
],
title: Column(
children: [
Text(
'Filter',
style: TextStyle(fontSize: 22, color: Colors.amberAccent),
),
],
),
),
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
children: [
Text(
'What are the Options ?',
style: TextStyle(fontSize: 16, color: Colors.white),
),
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: firstDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
firstDropdownValue = newValue!;
});
},
items: <String>['Option A', 'Option B']
.map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
if(firstDropdownValue.isNotEmpty)
DropdownButton<String>(
dropdownColor: Colors.blueGrey.shade700,
value: secondDropdownValue,
icon: const Icon(Icons.arrow_downward),
elevation: 16,
style: const TextStyle(color: Colors.white),
underline: Container(
height: 2,
color: Colors.blueGrey.shade900,
),
onChanged: (String? newValue) {
setState(() {
secondDropdownValue = newValue!;
});
},
items: <String>[
firstDropdownValue == 'Option A' ?
...['Option 1',
'Option 2',
'Option 3'] : ...['Option 5',
'Option 6',
'Option 7']
].map<DropdownMenuItem<String>>((String doaValue) {
return DropdownMenuItem<String>(
value: doaValue,
child: Text(doaValue),
);
}).toList(),
),
],
),
),
),
);
}
}

I want to change color of radio button dot in red when it is selected

Radio<String>(
activeColor: WHITE,
value: "video",
groupValue: _radioBtnVal,
onChanged: _handleChange),
Text(
"Video Call",
style: TextStyle(
color: _radioBtnVal == 'video' ? WHITE : BLACK,
fontWeight: FontWeight.bold),
),
Try below code hope its help to you, refer documentation here
Declare one enum
enum SingingCharacter { clickradio}
Your Widget
ListTile(
title: const Text('Click Radio'),
leading: Radio<SingingCharacter>(
activeColor: Colors.red,
value: SingingCharacter.clickradio,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
),
Your Output Screen ->

How do I give spacing between Expansionpanels in ExpansionPanellist in Flutter?

My app contains multiple cards with check box which makes wheather a work is done or not.
I want to create expansion panel list which contains multiple expansion panel. But when i want to give 16px spacing between each ExpansionPanels when it's not expanded but there is no option to do that. Can you please help.
If there is any other alternative to design this layout please help.
ExpansionPanelList(
// animationDuration: Duration(milliseconds: 10),
expandedHeaderPadding: EdgeInsets.only(top: 08),
elevation: 0,
children: [
ExpansionPanel(
isExpanded: _isOpen[0],
headerBuilder: (context, isOpen) {
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 12, horizontal: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"0 Month",
style: ThemeText.s18w500Black,
),
Visibility(
visible: toggele0[0] && toggele0[1] && toggele0[2],
child: Row(
children: [
SvgPicture.asset(
"assets/icons/icon-vaccination-check.svg"),
SizedBox(
width: 6.5,
),
Text(
"Done",
style: ThemeText.s12w400Green2,
),
],
),
)
],
),
);
},
body: Column(
children: [
CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
activeColor: HexColor(HexColors.textColorGreen2),
title: Text(
"Oral Polio Vaccine (2nd dose)",
style: ThemeText.s16w400Black.copyWith(
decoration: toggele0[0]
? TextDecoration.lineThrough
: TextDecoration.none),
),
subtitle: Text("Protects against Poliomyelitis"),
value: toggele0[0],
onChanged: (value) {
setState(() {
toggele0[0] = !toggele0[0];
});
}),
CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
activeColor: HexColor(HexColors.textColorGreen2),
title: Text(
"Oral Polio Vaccine (2nd dose)",
style: ThemeText.s16w400Black.copyWith(
decoration: toggele0[1]
? TextDecoration.lineThrough
: TextDecoration.none),
),
subtitle: Text("Protects against Poliomyelitis"),
value: toggele0[1],
onChanged: (value) {
setState(() {
toggele0[1] = !toggele0[1];
});
}),
CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
activeColor: HexColor(HexColors.textColorGreen2),
title: Text(
"Oral Polio Vaccine (2nd dose)",
style: ThemeText.s16w400Black.copyWith(
decoration: toggele0[2]
? TextDecoration.lineThrough
: TextDecoration.none),
),
subtitle: Text("Protects against Poliomyelitis"),
value: toggele0[2],
onChanged: (value) {
setState(() {
toggele0[2] = !toggele0[2];
});
})
],
)),
ExpansionPanel(
isExpanded: _isOpen[1],
headerBuilder: (context, isOpen) {
return Padding(
padding: const EdgeInsets.symmetric(
vertical: 12, horizontal: 15),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"1 Month",
style: ThemeText.s18w500Black,
),
Visibility(
visible: toggele1[0] && toggele1[1] && toggele1[2],
child: Row(
children: [
SvgPicture.asset(
"assets/icons/icon-vaccination-check.svg"),
SizedBox(
width: 6.5,
),
Text(
"Done",
style: ThemeText.s12w400Green2,
),
],
),
)
],
),
);
},
body: Column(
children: [
CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
activeColor: HexColor(HexColors.textColorGreen2),
title: Text(
"Oral Polio Vaccine (2nd dose)",
style: ThemeText.s16w400Black.copyWith(
decoration: toggele1[0]
? TextDecoration.lineThrough
: TextDecoration.none),
),
subtitle: Text("Protects against Poliomyelitis"),
value: toggele1[0],
onChanged: (value) {
setState(() {
toggele1[0] = !toggele1[0];
});
}),
CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
activeColor: HexColor(HexColors.textColorGreen2),
title: Text(
"Oral Polio Vaccine (2nd dose)",
style: ThemeText.s16w400Black.copyWith(
decoration: toggele1[1]
? TextDecoration.lineThrough
: TextDecoration.none),
),
subtitle: Text("Protects against Poliomyelitis"),
value: toggele1[1],
onChanged: (value) {
setState(() {
toggele1[1] = !toggele1[1];
});
}),
CheckboxListTile(
controlAffinity: ListTileControlAffinity.leading,
activeColor: HexColor(HexColors.textColorGreen2),
title: Text(
"Oral Polio Vaccine (2nd dose)",
style: ThemeText.s16w400Black.copyWith(
decoration: toggele1[2]
? TextDecoration.lineThrough
: TextDecoration.none),
),
subtitle: Text("Protects against Poliomyelitis"),
value: toggele1[2],
onChanged: (value) {
setState(() {
toggele1[2] = !toggele1[2];
});
})
],
)),]),

How to make a "link" from CheckboxlistTile to another page on Flutter

I'm making a Terms and Conditions agreement and I want this sentence to be highlighted and clickable, when clicked it should take the user to another page in the app where they can read the agreement. I'm having trouble creating something that's both clickable and highlighted.
Here is my code:
CheckboxListTile(
value: checkboxValue,
onChanged: (val) {
if (checkboxValue == false) {
setState(() {
checkboxValue = true;
});
} else if (checkboxValue == true) {
setState(() {
checkboxValue = false;
});
}
},
subtitle: !checkboxValue
? Text(
'Required.',
style: TextStyle(color: Colors.red),
)
: null,
title: new Text(
'I agree to the Terms and Conditions.',
style: TextStyle(fontSize: 14.0),
),
controlAffinity: ListTileControlAffinity.leading,
activeColor: Colors.green,
),
```
Wrap your Text widget with a GestureDetector(). See code below
CheckboxListTile(
value: checkboxValue,
onChanged: (val) {
setState(() {
checkboxValue = !checkboxValue;
});
},
subtitle: !checkboxValue
? Text(
'Required.',
style: TextStyle(color: Colors.red),
)
: null,
title: GestureDetector(
onTap: (){
Navigator.of(context).push(
MaterialPageRoute(
builder: (BuildContext context){
return Page();
},
),
);
},
child: Text(
'I agree to the Terms and Conditions.',
style: TextStyle(fontSize: 14.0),
),
),
controlAffinity: ListTileControlAffinity.leading,
activeColor: Colors.green,
)
Wrap your text with Inkwell or GestureDetector.
Sample code here:
GestureDetector(
onTap: () { },
child: Text(
"Sample Text",
style: TextStyle(
fontWeight: FontWeight.w800, color: Colors.blue
),
),
)