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.