Search code examples
flutterflutter-layoutflutter-dependenciesflutter-getx

Getx not updating the UI attributes flutter


I'm trying to change the color of my container on ontap event (inside gridview builder). It was working fine when I was using setState. But as I changed it to Getx, the print statement is working fine but the color of container is not changing. here is the code.

Here is the screens where I'm trying to display my gridview

class _SelectRoleScreenState extends State<SelectRoleScreen> {
  MyController myController = Get.put(MyController());
  var colorFromController;

  int selctedValue;

  @override
  Widget build(BuildContext context) {
    return SafeArea(
      child: Scaffold(
        body: SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: [
              Container(
                width: double.infinity,
                height: 250.0,
                child: upperPortion(),
              ),
              Padding(
                padding: EdgeInsets.all(8.0),
                child: GridView.builder(
                    shrinkWrap: true,
                    primary: false,
                    itemCount: myController.roles.length,
                    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
                      crossAxisCount: 2,
                      mainAxisSpacing: 16,
                      crossAxisSpacing: 20,
                    ),
                    itemBuilder: (context, index) {
                      return GestureDetector(
                        onTap: () {
                          colorFromController =
                              myController.selectedColor.value;
                          colorFromController = index;
                          print(colorFromController);
                          // setState(() {
                          //   _selectedColor = index;
                          // });
                        },
                        child: Padding(
                          padding: EdgeInsets.only(bottom: 8),
                          child: Obx(
                            () => Container(
                              width: sizeWidth(context) / 2.5,
                              decoration: BoxDecoration(
                                color: colorFromController == index
                                    ? primaryColor
                                    : Colors.white,
                                borderRadius: BorderRadius.circular(10),
                                boxShadow: [
                                  BoxShadow(
                                    color: Colors.grey[200],
                                    blurRadius: 2,
                                    offset: Offset(0, 5),
                                  ),
                                ],
                              ),
                              child: Column(
                                mainAxisAlignment:
                                    MainAxisAlignment.spaceBetween,
                                children: [
                                  SizedBox(
                                    height: 5,
                                  ),
                                  Image.asset(
                                    myController.roles[index]['roleImage'],
                                    color: colorFromController == index
                                        ? Colors.white
                                        : primaryColor,
                                    height: 50,
                                    width: 50,
                                  ),
                                  Text(
                                    myController.roles[index]['roleName']
                                        .toUpperCase(),
                                    style: TextStyle(
                                      fontSize: 16,
                                      color: colorFromController == index
                                          ? Colors.white
                                          : Colors.black,
                                    ),
                                  ),
                                  Container(
                                    width: 150,
                                    child: Text(
                                      myController.roles[index]
                                          ['roleDescription'],
                                      style: TextStyle(
                                        color: colorFromController == index
                                            ? Colors.white
                                            : Colors.black,
                                        fontSize: 12,
                                      ),
                                      textAlign: TextAlign.center,
                                    ),
                                  ),
                                  SizedBox(
                                    height: 5,
                                  ),
                                ],
                              ),
                            ),
                          ),
                        ),
                      );
                    }),
              ),
              SizedBox(
                height: 15,
              ),
              CustomButton(
                buttonText: "Get Started",
                buttonColor: primaryColor,
                textColor: Colors.white,
                onPress: () {
                  Navigator.push(
                    context,
                    MaterialPageRoute(
                        builder: (context) => CreateAccountPartnerScreen()),
                  );
                },
              ),
              SizedBox(
                height: 15,
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Here is the controller class

import 'package:get/get.dart';

class MyController extends GetxController {
  final RxInt selectHomeScreen = 0.obs;
  RxInt selectedColor = 1.obs;

  List<Map> roles = [
    {
      'roleImage': 'assets/icons/select_partner/Pet Shop.png',
      'roleName': "pet shop",
      'roleDescription': 'Sell Your Products to Pet Lovers',
      'homeIndex': 0,
    },
    {
      'roleImage': 'assets/icons/select_partner/Sitter.png',
      'roleName': "Sitter",
      'roleDescription': 'Provide Pet Sitter Services',
      'homeIndex': 1,
    },
    {
      'roleImage': 'assets/icons/select_partner/Vets Clinic.png',
      'roleName': "Vets Clinic",
      'roleDescription': 'Do Appointments with Pet Lovers',
      'homeIndex': 2,
    },
    {
      'roleImage': 'assets/icons/select_partner/Groomer.png',
      'roleName': "Groomer",
      'roleDescription': 'Do Grooming Appointments with Pet Lovers',
      'homeIndex': 3,
    },
    {
      'roleImage': 'assets/icons/select_partner/Aglity Trainer.png',
      'roleName': "Aglity Trainer",
      'roleDescription': 'Train Pets Different Skills',
      'homeIndex': 4,
    },
    {
      'roleImage': 'assets/icons/select_partner/Govertment.png',
      'roleName': "Govertment",
      'roleDescription': 'Renew Pets Licences and Apply For Pets Passport',
      'homeIndex': 5,
    },
  ].obs;
}

Any help would be appreciated


Solution

  • The reason it's not rebuilding is because your onTap isn't changing any variable from the GetX class. This is intended behavior to minimize unnecessary rebuilds.

    All you need to do is change the actual GetX variable in the onTap of your gesture detector.

     onTap: () {
          myController.selectedColor.value = index;
          print(colorFromController);
       },
    

    Then within your BoxDecoration make the logic depend on the GetX variable and not a local one.

    Obx(
      () => Container(
        width: sizeWidth(context) / 2.5,
        decoration: BoxDecoration(
          color: myController.selectedColor.value == index
               ? primaryColor
               : Colors.white,
    .....
    

    Essentially you don't need the local colorFromController variable. Just replace it with myController.selectedColor.value in the whole page.

    I also suggest just putting the primaryColor variable in the GetX class as well and make the whole page stateless since you're not doing anything that requires a stateful widget.