How to place these two buttons on the left? - flutter

I'm trying to put these two buttons on the left, but to no avail. Can you give me any tips on how to make them stay on the left margin? I've tried to remove the Container and align using only the Row, but without success.
Container(
alignment: AlignmentDirectional.bottomStart,
padding: EdgeInsets.fromLTRB(0.0, 5.0, 70.0, 5.0),
child: Row(
children: [
Expanded(
child: ListTile(
title: const Text('CPF'),
leading: Radio<SingingCharacter>(
value: SingingCharacter.cpf,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
),
),
Expanded(
child: ListTile(
title: const Text('RNE'),
leading: Radio<SingingCharacter>(
value: SingingCharacter.rne,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
),
),
],
),
),

ListTile occupies an entire row, and if you wrap each ListTile with Expanded widget then it gets divided into 2 ListTile in the same row.
So if you want to create 2 Radio's and align them into the left row, then don't use listTile and expanded.
Instead create a row, pass 2 columns. Each column will have 2 Widgets. A text widget and a Radio Widget. That's how you can achieve your desired outlook.
Scaffold(
appBar: AppBar(),
body: Column(children: [
Row(
children: [
Column(
children: [
const Text("Radio 1"),
Radio<SingingCharacter>(
value: SingingCharacter.cpf,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
],
),
const SizedBox(
width: 20,
),
Column(
children: [
const Text("Radio 2"),
Radio<SingingCharacter>(
value: SingingCharacter.rne,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
],
),
],
)
]),
);

Container(
alignment: AlignmentDirectional.bottomStart,
padding: EdgeInsets.fromLTRB(0.0, 5.0, 70.0, 5.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.start, // add this line
children: [
// Expanded(
// child:
ListTile(
title: const Text('CPF'),
leading: Radio<SingingCharacter>(
value: SingingCharacter.cpf,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
),
// ),
// Expanded(
// child:
ListTile(
title: const Text('RNE'),
leading: Radio<SingingCharacter>(
value: SingingCharacter.rne,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
),
// ),
],
),
),

the closest I got was using this code:
Row(
children: [
Expanded(
child:
ListTile(
contentPadding: EdgeInsets.only(left: 0.0,),
title: const Text('CPF'),
leading: Radio<SingingCharacter>(
value: SingingCharacter.cpf,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
),
),
Expanded(
child:
ListTile(
contentPadding: EdgeInsets.only(left: 0.0,),
title: const Text('RNE'),
leading: Radio<SingingCharacter>(
value: SingingCharacter.rne,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
),
),
],
),

Related

How do I reduce the space between Radio Buttons and shift them more towards left in Flutter

I have implemented Radio button in Flutter namely 'Today' , 'Tomorrow' , 'User Input Date', and have wrapped them in a Column, but I am unable to reduce the space between the 3 radio buttons and also I am not able to move them towards the left. Is there any way I can shift them towards left side and decrease the default space taken between the radio button. Also I want to stick to the use of RadioListTile only.
I am attaching a picture to give a clear idea.
Code
Column(
children: [
RadioListTile<DateTime>(
activeColor: Colors.white,
title: Text(
"Today",
style: Theme.of(context).textTheme.bodyMedium,
),
value: today,
groupValue: selectedMatchDateFilter,
onChanged: (DateTime? value) => setState(() {
selectedMatchDateFilter = value;
}),
),
RadioListTile<DateTime>(
activeColor: Colors.white,
title: Text(
"Tomorrow",
style: Theme.of(context).textTheme.bodyMedium,
),
value: DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day + 1),
groupValue: selectedMatchDateFilter,
onChanged: (DateTime? value) => setState(() {
selectedMatchDateFilter = value;
}),
),
RadioListTile<DateTime>(
activeColor: Colors.white,
title: Row(
children: [
DropdownButton2<String>(
isExpanded: true,
buttonHeight: 30.h,
buttonWidth: 220.w,
items: const [
DropdownMenuItem<String>(
value: "",
child: Text("Till Date"),
),
DropdownMenuItem<String>(
value: "",
child: Text("Precise Date"),
),
],
),
1 == 2
? Checkbox(
value: true,
onChanged: (bool? _value) {},
)
: IconButton(
icon: const Icon(Icons.calendar_today),
onPressed: () => showDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: DateTime(2022, 11, 16),
lastDate: DateTime(2023, 1, 1),
),
),
],
),
value: DateTime.now(),
groupValue: selectedMatchDateFilter,
onChanged: (value) {},
)
],
),
You can add visualDensity and dense and contentPadding like this:
RadioListTile<DateTime>(
activeColor: Colors.white,
visualDensity: VisualDensity(horizontal: -4, vertical: -4),//<-- add this
dense: true,//<-- add this
contentPadding: EdgeInsets.zero,//<-- add this
title: Text(
"Tomorrow",
style: Theme.of(context).textTheme.bodyMedium,
),
value: DateTime(DateTime.now().year, DateTime.now().month,
DateTime.now().day + 1),
groupValue: selectedMatchDateFilter,
onChanged: (DateTime? value) => setState(() {}),
),
you can't get better than this, if its not good for you, you need make a custom tile like this:
Widget CustomRadioTile<T>(
{required Function(T?) onChanged,
required String title,
required T groupValue,
required T value,
required BuildContext context}) {
return InkWell(
onTap: () {
onChanged(value);
},
child: Row(
children: [
SizedBox(
height: 20,
width: 20,
child: Radio<T>(
value: value,
groupValue: groupValue,
onChanged: (value) {},
),
),
Padding(
padding: const EdgeInsets.only(left: 4.0),
child: Text(
title,
style: Theme.of(context).textTheme.bodyMedium,
),
),
],
),
);
}
and use it like this:
CustomRadioTile<DateTime>(
onChanged: (DateTime? value) => setState(() {
selectedMatchDateFilter = value;
}),
title: 'Tomorrow',
groupValue: selectedMatchDateFilter,
value: DateTime(DateTime.now().year, DateTime.now().month,
DateTime.now().day + 1),
context: context),
There isn't any options to change the width between the Radio and Text itself.
Instead you can create a separate widget which combines Radio and Text widgets.
class LabeledRadio extends StatelessWidget {
const LabeledRadio({
super.key,
required this.label,
required this.padding,
required this.groupValue,
required this.value,
required this.onChanged,
});
final String label;
final EdgeInsets padding;
final bool groupValue;
final bool value;
final ValueChanged<bool> onChanged;
#override
Widget build(BuildContext context) {
return InkWell(
onTap: () {
if (value != groupValue) {
onChanged(value);
}
},
child: Padding(
padding: padding,
child: Row(
children: <Widget>[
Radio<bool>(
groupValue: groupValue,
value: value,
onChanged: (bool? newValue) {
onChanged(newValue!);
},
),
Text(label),
],
),
),
);
}
}
Use this widget as a radio box then replace RadioListTile with this.

how to make unselected color using radiotiles

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

How to add flutter radio button with right side of image

I'm beginner for the flutter and I'm try to added radio button with right side to images , but its not working correctly, anyone know how to do that correctly
Thanks
here the code
Container(
margin: const EdgeInsets.all(15.0),
padding: const EdgeInsets.all(3.0),
decoration: BoxDecoration( borderRadius: BorderRadius.circular(8),
border: Border.all( color: Color(0xFFD8D8D8),)
),
child: Column( mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: <Widget>[
ListTile(
title: const Text('Debit Card'),
leading: Radio<SingingCharacter>(
value: SingingCharacter.lafayette,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
),
ListTile(
title: const Text('Credit Card'),
leading: Radio<SingingCharacter>(
value: SingingCharacter.jefferson,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
),
],
),
),
I Think you use RadioListTile try to below answer Hope it help.
enum SingingCharacter { one, two }
SingingCharacter? _character = SingingCharacter.one;
//Your Widget
Column(
children: <Widget>[
RadioListTile<SingingCharacter>(
title: const Text('Credit Card'),
value: SingingCharacter.one,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
RadioListTile<SingingCharacter>(
title: const Text('Debit Card'),
value: SingingCharacter.two,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
],
);
Or You Add this Radio Button on right side of the Name Just use the trailing in Listview insted of leading.
Column(
children: <Widget>[
ListTile(
title: const Text('Credit Card'),
trailing: Image.network('https://picsum.photos/250?image=9'),
leading: Radio<SingingCharacter>(
value: SingingCharacter.one,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
),
ListTile(
title: const Text('Debit Card'),
trailing: Image.network('https://picsum.photos/250?image=9'),
leading: Radio<SingingCharacter>(
value: SingingCharacter.two,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
},
),
),
],
)
Your Screen using RadioListTile ->
Your screen using ListTile with image
You can use like this:
ListTile(
title: const Text('Debit Card'),
trailing: Radio( // type code here
you might want to use a RadioListTile Instead of a ListTile
RadioListTile<SingingCharacter>(
title: Text('Credit Card'),
controlAffinity: ListTileControlAffinity.trailing,//**this will help align the control to the right**
value: SingingCharacter.jefferson,
groupValue: _character,
onChanged: (SingingCharacter? value) {
setState(() {
_character = value;
});
);

Using Visibility Widget in Flutter to toggle widgets display

I have a Column widget I'd only like to make visible when a user taps on the add new button. I am using the Visibility widget Flutter provides and I am using setState() to change the visible property in the Visibility widget class. It doesn't work.
What could I be overlooking? Find my code snippet below:
bool _addNewTax = false;
FlatButton.icon(
color: kBgCircleColour,
padding: EdgeInsets.all(15.0),
icon: Icon(
FontAwesomeIcons.plusSquare,
color: kThemeStyleButtonFillColour,
),
onPressed: () {
setState(() {
_addNewTax = true;
});
Visibility(
visible: _addNewTax,
child: _buildTaxInputFields(),
);
},
label: Text(
'Add new tax',
style: kRegularTextStyle,
),
);
My _buildTaxInputFields function as below:
_buildTaxInputFields() {
return Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.all(20.0),
child: TextFormField(
initialValue: inputValue,
textAlign: TextAlign.left,
onSaved: () {},
decoration: kTextFieldDecoration.copyWith(hintText: 'tax name e.g. VAT, service charge, etc'),
),
Padding(
padding: const EdgeInsets.all(20.0),
child: TextFormField(
initialValue: inputValue,
textAlign: TextAlign.left,
onSaved: () {},
decoration: kTextFieldDecoration.copyWith(hintText: 'tax percentage e.g. 20, 19.5'),
),
Row(
children: <Widget>[
Expanded(
flex: 1,
child: RadioListTile(
title: Text('I\'ll bear it '),
value: TaxBearer.merchant,
groupValue: _taxBearer,
onChanged: (TaxBearer value) {
setState(() {
_taxBearer = value;
});
},
),
),
Expanded(
flex: 1,
child: RadioListTile(
title: Text('Push to customer'),
value: TaxBearer.customer,
groupValue: _taxBearer,
onChanged: (TaxBearer value) {
setState(() {
_taxBearer = value;
});
}),
),
],
),
],
);
}
Your visibility widget will never be rendered because you're generating it in the onPressed method of a button.
You could use a column to generate it below the button like this:
bool _addNewTax = false;
Column(
children: [
FlatButton.icon(
color: kBgCircleColour,
padding: EdgeInsets.all(15.0),
icon: Icon(
FontAwesomeIcons.plusSquare,
color: kThemeStyleButtonFillColour,
),
onPressed: () {
setState(() {
_addNewTax = true;
});
},
label: Text(
'Add new tax',
style: kRegularTextStyle,
),
),
Visibility(
visible: _addNewTax,
child: _buildTaxInputFields(),
),
],
);

How to get this kind of radio button in flutter

I am trying to create a gender selection functionality that contains 3 radio buttons. I have done this code but it is not working as I want it.
Radio button container
final _radio_colume_container = Container(
margin: const EdgeInsets.fromLTRB(50, 15, 50, 00),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'Gender*',
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
add_radio_button(0, 'Male'),
add_radio_button(1, 'Female'),
add_radio_button(2, 'Others'),
],
),
],
),
);
add_radio_button Method
Row add_radio_button(int btnValue, String title) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Radio(
activeColor: Colors.green,
value: btnValue,
groupValue: -1,
onChanged: _handleradiobutton,
),
Text(title)
],
);
}
I am achieving this
I want to achieve this.
List gender=["Male","Female","Other"];
String select;
Row addRadioButton(int btnValue, String title) {
return Row(
mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
Radio(
activeColor: Theme.of(context).primaryColor,
value: gender[btnValue],
groupValue: select,
onChanged: (value){
setState(() {
print(value);
select=value;
});
},
),
Text(title)
],
);
}
//Use the above widget where you want the radio button
child: Row(
children: <Widget>[
addRadioButton(0, 'Male'),
addRadioButton(1, 'Female'),
addRadioButton(2, 'Others'),
],
),
You should take a look at RadioListTile as it provides a dense property which will help reduce the padding between the button and its title.
After applying some refactoring from #Shubham's answer, presenting a generalized version of the code for multiple purposes.
import 'package:flutter/material.dart';
/// Requires a list of string ['Male','Female','Other'] only once.
class GenderField extends StatelessWidget {
final List<String> genderList;
GenderField(this.genderList);
#override
Widget build(BuildContext context) {
String select;
Map<int, String> mappedGender = genderList.asMap();
return StatefulBuilder(
builder: (_, StateSetter setState) => Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
mainAxisSize: MainAxisSize.min,
children: [
Text(
'Gender : ',
style: TextStyle(fontWeight: FontWeight.w400),
),
...mappedGender.entries.map(
(MapEntry<int, String> mapEntry) => Row(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Radio(
activeColor: Theme.of(context).primaryColor,
groupValue: select,
value: genderList[mapEntry.key],
onChanged: (value) => setState(() => select = value),
),
Text(mapEntry.value)
]),
),
],
),
);
}
}
In the main.dart, this widget can be called as
// Some code
Padding(
padding: EdgeInsets.only(bottom: 10),
child: GenderField(['Male','Female','Other'])
)
Padding(
padding: EdgeInsets.only(left: 5, right: 5),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
"Gender",
style: TextStyle(fontSize: 19),
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: ListTile(
title: const Text('M'),
leading: Radio<Gender>(
fillColor:
MaterialStateColor.resolveWith(
(states) => Colors.blue),
value: Gender.male,
groupValue: _gen,
onChanged: (Gender? value) {
setState(() {
_gen = value;
});
},
),
),
),
Expanded(
child: ListTile(
title: const Text('F'),
leading: Radio<Gender>(
fillColor:
MaterialStateColor.resolveWith(
(states) => Colors.blue),
value: Gender.female,
groupValue: _gen,
onChanged: (Gender? value) {
setState(() {
_gen = value;
});
},
),
),
),
Expanded(
child: ListTile(
title: const Text('O'),
leading: Radio<Gender>(
fillColor:
MaterialStateColor.resolveWith(
(states) => Colors.blue),
value: Gender.other,
groupValue: _gen,
onChanged: (Gender? value) {
setState(() {
_gen = value;
});
},
),
),
),
])
])),