Home > Software design >  ValueListenableBuilder not changing the List of Color
ValueListenableBuilder not changing the List of Color

Time:09-16

i am able to change anything (such as int, String, visibility) that is not in a List in my codes but i can' t change my List of Color with ValueListenableBuilder.

**Here is my _gameField and gF_Pressed variables: **

  final ValueNotifier<List<Color>> _gameField = ValueNotifier(<Color>[
    Colors.black, Colors.black, Colors.black, Colors.black, Colors.black,
    Colors.black, Colors.black, Colors.black, Colors.black, Colors.black,
    Colors.black, Colors.black, Colors.black, Colors.black, Colors.black,
    Colors.black, Colors.black, Colors.black, Colors.black, Colors.black,
    Colors.black, Colors.black, Colors.black, Colors.black, Colors.black,
  ]);
  final ValueNotifier<bool> gF_pressed = ValueNotifier<bool>(false);

Here is my code: please have a look comment lines in codes.

First ValueListenableBuilder is for Visibility with valueListenable is gF_Pressed is working. But second one that is for GestureDetecture and used to change the color of the grid is not working and i am using _gameField as valueListenable parametre which is defined as ValueNotifier<List>

//**This ValueListenableBuilder is working.**

        ValueListenableBuilder(
              valueListenable: gF_pressed,
              builder: (BuildContext context, value, Widget child) {
                return Visibility( visible: gF_pressed.value == true ? true : false,
                  child: Center(
                    child: Container(
                      ...
                      child: Card(
                        child: Center(
                          child: GridView.count(
                          ...
                            children: [

// this ValueListenableBuilder is for changing the Color of a grid and i am using _gameField  
// list's colors here but listen is not working here for the List. 

                              ValueListenableBuilder(
                                valueListenable: _gameField,
                                builder: (BuildContext context, value, Widget child) {
                                  return GestureDetector(
                                    onTap: (){
                                      if (timePressed.value != true) {
                                        timePressAlert();
                                      } else {
                                        if (pushes.last == 1 || pushes.last == 5) {
                                          _gameField.value[pushes.last] = _gameField.value[0];
                                          _gameField.value[0] = Colors.black;
                                          pushes.add(0);
                                        }
                                      }
                                    },
                                    child: Container(
                                      color: _gameField.value[0],
                                    ),
                                  );
                                },
                              ),
                              ...
                            ],                      
...

i hope i can get a help for this.

CodePudding user response:

The problem here is that you are changing the elements inside the List<Color> but not the list itself. ValueNotifiers only notice the change if you change the value itself like:

_gameField.value = [...] // <- New color list here.

But for this you need to copy the whole list everytime and change few elements.


EDIT:

If you want to implement a method then you can do it like this:

void colorChangeNotifier(int index) {
  List<Color> newList = List.from(_gameField.value); //This copies all elements
  // Modify here newList as you wish.
  _gameField.value = newList;
}

Another way is to notify a change explicitly with:

_gameField.notifyListeners()

But this is meant to be called inside the ValueNotifier. That's why it leads to syntax warning if we use it.

My recommendation is to write a new class (something like ColorGrid) which extends ChangeNotifier. It holds a list of Color and provide a method to change individual elements of this list. Once you set a color, you call notifyListeners() inside this method. It can look like this:

class ColorGrid extends ChangeNotifier{

  List<Color> colors = [
    Colors.black, Colors.black, Colors.black, Colors.black, Colors.black,
    Colors.black, Colors.black, Colors.black, Colors.black, Colors.black,
    Colors.black, Colors.black, Colors.black, Colors.black, Colors.black,
    Colors.black, Colors.black, Colors.black, Colors.black, Colors.black,
    Colors.black, Colors.black, Colors.black, Colors.black, Colors.black,
  ];

  void setColor(int index, Color, color) {
    colors[index] = color;
    notifyListeners();
  }
}

CodePudding user response:

i have made a function that changes the _gameField List itself. Here is the function:

void colorChangeNotifier(int index) {
    ValueNotifier<List<Color>> new_gF = ValueNotifier(<Color>[]);

    _gameField.value[pushes.last] = _gameField.value[index];
    _gameField.value[index] = Colors.black;
    pushes.add(index);
    print(pushes);
    print(pushes.length);

     _gameField.value.forEach((color) {
       new_gF.value.add(color);
     });
     _gameField.value = new_gF.value;
     _gameField.notifyListeners();
  }

in this Function i am changing the target element at first, after that adding all of the elements of _gameField List to new_gF and at last making value of _gameField list equals to my new_gF list' s value. So _gameField list's value is taking it's new value.

  • Related