'Flutter change button color when clicked in a list of buttons
I have a list of buttons in my app and each button is supposed to filter a list of items. All buttons have the same color, I want such that only one button has an active color no matter which button is clicked. Currently I end up changing the color of all buttons when I click one button.
Here is my code
final blueColors = const Color(0xff295a7c);
final blueShades = const Color(0xffccdef2);
final blackColors = const Color(0xff000000);
final whiteColors = const Color(0xffffffff);
Padding(
padding: const EdgeInsets.all(10),
child: SizedBox(
height: 40,
child: ListView(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
children: [
Padding(
padding: const EdgeInsets.all(3),
child: Obx(
() => TextButton(
onPressed: () {
controller.changeButton();
},
child: Text(
'All',
style: theme.textTheme.bodyText2!.copyWith(
color: controller.whenPressed.value == true ? whiteColors : blackColors,
fontSize: 13,
fontWeight: FontWeight.w400,
),
),
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor:
controller.whenPressed.value == true
? blueColors
: blueShadeColors,
onSurface: Colors.grey,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
),
),
),
),
Padding(
padding: const EdgeInsets.all(3),
child: Obx(
() => TextButton(
onPressed: () {
controller.changeButton();
},
child: Text(
'option 2',
style: theme.textTheme.bodyText2!.copyWith(
color: controller.whenPressed.value == true ? whiteColors : blackColors,
fontSize: 13,
fontWeight: FontWeight.w400,
),
),
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor:
controller.whenPressed.value == true
? blueColors
: blueShadeColors,
onSurface: Colors.grey,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
),
),
),
),
Padding(
padding: const EdgeInsets.all(3),
child: Obx(
() => TextButton(
onPressed: () {
controller.changeButton();
},
child: Text(
'option 3',
style: theme.textTheme.bodyText2!.copyWith(
color: controller.whenPressed.value == true ? whiteColors : blackColors,
fontSize: 13,
fontWeight: FontWeight.w400,
),
),
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor:
controller.whenPressed.value == true
? blueColors
: blueShadeColors,
onSurface: Colors.grey,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
),
),
),
),
Padding(
padding: const EdgeInsets.all(3),
child: Obx(
() => TextButton(
onPressed: () {
controller.changeButton();
},
child: Text(
'option 4',
style: theme.textTheme.bodyText2!.copyWith(
color: controller.whenPressed.value == true ? whiteColors : blackColors,
fontSize: 13,
fontWeight: FontWeight.w400,
),
),
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor:
controller.whenPressed.value == true
? blueColors
: blueShadeColors,
onSurface: Colors.grey,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
),
),
),
),
],
),
),
),
I am using Getx for statemananegement. Here is my controller code.
var whenPressed = false.obs;
void changeButton() {
whenPressed.value = !whenPressed.value;
update();
}
How can I modify it such that only one button will get the active button color on any click event
Solution 1:[1]
I found a way to do what to change the button color of a single button when pressed.
I added this code to the controller
var _selectedButton = 0.obs;
List<String> categories = [
'All',
'Option 1',
'Option 2',
'Option 3',
'Option 4',
'Option 5',
];
Then added this method
int changeButton(int index) {
_selectedButton.value = index;
update();
return _selectedButton.value;
}
Finally I replaced the view with this code
ListView.separated(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
itemBuilder: (context, index) {
return Obx(
() => TextButton(
onPressed: () {
controller.changeButton(index);
},
child: Text(
controller.categories[index],
style: theme.textTheme.bodyText2!.copyWith(
color: controller._selectedButton.value == index
? whiteColor
: blackColor,
fontSize: 13,
fontWeight: FontWeight.w400,
),
),
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor:
controller._selectedButton.value == index
? blueColor
: blueShadeColor,
onSurface: Colors.grey,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(20),
),
),
),
),
);
},
itemCount: controller.categories.length,
separatorBuilder: (context, index) =>
const SizedBox(width: 5),
),
Solution 2:[2]
The problem your all buttons use same controller. I guess you have code like this in your page.
final controller = Get.put(Controller());
// maybe you put controller on another area then you used like this
//final controller = Get.find<Controller>();
use different controller for your buttons, remember if you do not set tag to controller, they will not be different
final controllerAll = Get.put(Controller(), tag: "ALL");
final controllerOption1 = Get.put(Controller(), tag: "OPTION1");
final controllerOption2 = Get.put(Controller(), tag: "OPTION2");
final controllerOption3 = Get.put(Controller(), tag: "OPTION3");
Therefore when you click any button, only that button will have active color.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Kevnlan |
Solution 2 | Ugur Aydogdu |