Flutter. How to correctly update state of nested widgets? - flutter

I'm new in flutter and I'm trying to implement something like radio group with custom buttons in Android. For this I created StatefulWidget, which hold list of selectable buttons. For every button I was set press listener where I do something like this:
setState(() {
buttons.forEach((button) => button.isSelected = false);
buttons[selectedButtonIndex].isSelected = true;
});
And then my CustomButtonWidget changes color depending on the parameter isSelected .
All this works well. However, I have an additional requirement. I need my RadioGroupWidget to return the selected button type. For this I created a callback :
final ValueChanged<ButtonType> onChanged;
And now my button press listener looking like this:
onTap: () {
setState(() {
buttons.forEach((button) => button.isSelected = false);
buttons[selectedButtonIndex].isSelected = true;
});
onChanged(buttons[selectedButtonIndex].type);
}
Next I get this type of button in my other widget which is using RadioGroupWidget:
CustomRadioGroup(
onChanged: (value) {
setState(() {
buttonType= value;
});
}),
)
As you can see I call again setState. This is what leads to the problem. But I need to do this, because I need to update the state of another widget (for example let's call it InfoWidget) depending on the selected button.
After all these manipulations, the state of the InfoWidget is updated correctly, but the state of the selected button in the RadioGroupWidget does not change. I tried to debug this and I see that at first the parameter isSelected is set to true for the desired button, but after the state of the button I selected is not updated, because its parameter isSelected becomes false. And I don't understand why this is happening.
Please help, I am completely confused.

Related

How can I change or override android/ios back button's action in flutter

I need to make a change in my page (changing a bool in setState etc...) when the user presses the back button.
I looked it up and I know people use WillPopScope to override the default "back" action, but in all of the examples they were just popping the page, and I need to do a custom function instead of that, and have no Idea how to do so.
my function looks like this, and I need to run in when the user pressed the back button:
Future<void> backToCats() async{
setState(() {
isLoaded=false;
});
if(isFromSearch){
loadCategories();
}
setState(() {
showingBrands=false;
isLoaded=true;
});
}
You can perform custom logic in the onWillPop argument of a WillPopScope widget. Just make sure to return true or false at the end to indicate whether the page is allowed to pop. WillPopScope will activate for the back button, and other actions that automatically navigate back such as swiping from the side of the screen on iOS.
For example, if you need to set a bool to false in your stateful widget, it would look something like this
WillPopScope(
onWillPop: () async {
setState(() => myBool = false);
return true;
}
child: ...
);

How to stop page reloading in flutter after using setState in Checkbox

I use flutter web I put a checkbox for users. The problem is that the page contains a different TextField.So, in the event that the user selects one of the Checkbox options, a page refresh occurs.Then all TextField data is reloaded and all data that was previously inserted is deleted.The problem is caused by setState(()).But I can't delete it if the setState checkbox is deleted. The checkbox doesn't work.
bool _checkbox = false;
Checkbox(
value: _checkbox,
onChanged: (value) {
setState(() {
_checkbox = !_checkbox;
});
},
);
How can this problem be solved without deleting the data from the fields?
Thank you
wrap in StatefulBuilder to reload only the checkbox

What is the right way to change icon from selected to unselected in Flutter?

I am creating add to cart logic, so I created a function which is added items in the cart, but I don't understand how properly change icons from unselected to selected. So I was trying to do something like that:
void addToCart(Item prod) {
print('it works');
products.add(prod);
print('it works2');
}
Widget iconChage(){
if(_isPressed == true){
return Icon(Icons.ten_k);
}else{
return Icon(Icons.eleven_mp);
}
But it doesn't work when I put it to the widget tree. What is the right way to change the icon from selected to unselected?
Try this way:
Make a bool to use as condition:
bool isPressed = true;
Then use your icon like this:
Icon(isPressed? Icons.ten_k : Icons.eleven_mp)
When want to toggle the icon just simply do this:
setState(()=> isPressed = !isPressed)

How to disable click events for entire children except one selected child in flutter?

Scenario: I have number of children in Listview.builder. For every children there is button which invokes TTS(text to speech). I wanted when any one of child is pressed rest all children should be in Listview.builder un-clickable till pressed child finishes its TTS.
I got answer from google like absorb pointer, ignore pointer to solve this.
But i dont know how to implement above scenario using these widgets.
Store a bool in the State of the class enclosing the ListView.builder. This bool should store if one of the children is currently doing its TTS. If it is true you should set all of the onPressed(or equivalent) method to null to prevent other taps from triggering an action. Ex:
bool hasBeenClicked = false;
void yourTTSMethod() {
setState(() {
hasBeenClicked = true;
});
... //Do normal method body
setState(() {
hasBeenClicked = true;
});
}
//In build method with each `List` item:
GestureDetector(//Just for sample, use whatever click detector you're currently using
onTap: hasBeenClicked ? null : yourTTSMethod
)

RaisedButton stays null

Im trying to do a register page and everything is working but the logic for the onpressed property. This is my code:
onPressed: _usernameController.text == "" || _emailController.text == "" || _passwordController.text == "" || _passController.text == "" ? null : () {
setState(() {
_isLoading = true;
});
register(_usernameController.text, _emailController.text, _passwordController.text, _passController.text);
}
the button stays null even if you fill all the required fields as if the condition remained true. I know the code is right because I have a similar logic in my login page, and also whenever I refresh with the fields already full it magically lights up the button and everything works. What could be the problem?
You can use Form widget. Form widget has onChange property also you can listen to all states. Form widget has other property, the key is validated and control your form state. Don't forget must be declared validator property.
Same example:
Full code: Form Validattor
Please make one method like below..
void _registration(){
//add register code here instead of write at onPressed event
}
and call this method in onPressed event like this...
onPressed: _registration