how to have a button build a widget and have it setstate - flutter

I currently have a InkWell that builds a custom widget alert dialog when pressed using the build method below.
InkWell(
onTap: () => showDialog<String>(
context: context,
builder: (BuildContext context) => Popup(),
I also need it to set the state of some Bools and Int's when pressed which usually happens when using the setstate method.
can someone please show me how to do both build a widget and setstate when the button is pressed?
what would the code look like?
cheers

Make a function and set bools before you build the dialog. Then call the method in onTap:
buildMyDialog(){
myBool = false;
myInt = 2;
showDialog<String>(
context: context,
builder: (BuildContext context) => Popup(),
);
}
If you need your current UI to use the values, setState before showing dialog in the same method.

Related

Flutter: setState not updating UI after popping

I have a flutter application where the variable is initialized outside of the build function. In the build I have :
onPressed: (BuildContext context) async {
await showDialog(
context: context,
builder: (context) => Dialog(
...
Navigator.pop()
);
).then((_) => setState(() {
print("Test is this prints");
));
setState(){ flag = !flag }
}
The purpose of the setState is just so that the UI is updates after I close out of the dialog window. I have a util file that is makes some changes to the UI when I close out of the dialog, and I would like to see it reflected after I close out of the dialog.
For some reason, the UI is not changing even though setState should be rebuilding the widget since something changes.
When I do the .then(setState(){}), the console prints the print statement, but the UI is still not changing.
In which code or widget, you are using the flag variable.
If flag is not used in any of the widget then your UI will not be updated.
Remove multiple setState, just use one and also check usage of flag variable in your code.
.then((_) => setState(() {
flag = !flag
print("Test is this prints and updated flag value is $flag");
));
When rebuild by setState(), flag is also reset. So always flag is false.
Make it a variable inside the State class
onPressed: (BuildContext context) async {
await showDialog(
context: context,
builder: (context) => Dialog(
...
Navigator.pop()
);
).then((_) => setState(() {
print("Test is this prints");
flag = !flag
));
}

Flutter, refresh screen after await call

Currently the only way I have to refresh the screen is using Navigator.push().
if (response.statusCode == 200) {
print(await response.stream.bytesToString());
Navigator.push(
context,
new MaterialPageRoute(
builder: (context) => this.build(context)));
}
But this only adds another screen to the stack of screens.
How can I refresh the screen after calling my print() without having to use Navigator.push()?
Thanks!
You can set your class as Stateful Widget and use:
setState(() {
// Add, edit or delete widgets
// Set a diferent value for some variable
// etc...
});
Or you can still use the Navigator but with the pushReplacement function, for example:
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (BuildContext context) => super.widget));
use setState after request api response data,
setState is a way to dynamically change the UI.
It rebuild all current screen.
We call it inside the State Object class of the StatefulWidget.

disable android back while showModalBottomSheet opened

My widget inside showModalBottomSheet is a textfield , user must fill up correct value in order to proceed next function, I know there is a ready param called isDismissible , however it only disable from taping backdrop, it doesn't diable android back.
return showModalBottomSheet(
context: context,
builder: (BuildContext context) {
...
}
}
you can wrap your widget with WillPopScope
For example:
WillPopScope(
onWillPop: () async => false,
)

flutter: how to add a loading (ios style) in front of the page?

I'm new in flutter. I want a loading animation (iOS style) in front of the page. I have searched for flutter loading api but isn't what I want. How can I achieve it? Thanks in advance.
It has a property called barrierDismissible that if you set as false, the user won't be able to close or interact with the screen outside of it.
void _openLoadingDialog(BuildContext context) {
showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: CircularProgressIndicator(),
);
},
);
}
Once you're done with the API loading, call Navigator.pop(context); to dismiss the dialog.
To prevent the user from clicking the back button on the Dialog, dismissing it, envelop your Scaffold inside a WillPopScope widget and implement the onWillPop function.
#override
Widget build(BuildContext context) {
enter code here return WillPopScope(
child: Scaffold(
body: Container(),
) ,
onWillPop: _onBackButton
);
}
Future<bool> _onBackButton() {
// Implement your logic
return Future.value(false);
}
If you return false on it, the user won't be able to press the back button. So use any logic you desire, e.g 'If I'm loading return false, otherwise return true'.
or you can use Full-screen loader: Best solution to display a full screen loader is to use package this

Flutter - StreamBuilder builder function runs when navigator pops

I have a widget called RootContainer which receives a Widget child and wrap it inside a StreamBuilder:
class RootContainer extends StatelessWidget {
final Widget child;
RootContainer({this.child});
#override
Widget build(BuildContext context) {
return StreamBuilder<OverlayAlert>(
stream: ApiService.ThrottledException.stream,
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.active) {
Future.delayed(Duration.zero, () => showAlert(context, snapshot));
}
return this.child;
},
);
}
void showAlert(BuildContext context, snapshot) {
print("showing dialog");
showDialog(
context: context,
builder: (context) => OverlayAlertDialog(snapshot),
);
}
When an error occurs, I add a new value to the stream ApiService.exception.stream which triggers the StreamBuilder builder and then it opens a dialog.
This is the current widget tree:
The problem starts when I want to pop the navigator, the StreamBuilder.builder builds again!
I thought it may happen because the RootContainer is being rebuilt, but placing a print before the StreamBuilder has resulted in just one print.
I tried to .listen to the stream, and the stream didn't fire when I popped the navigator so I can confirm that there's nothing wrong with ApiService.ThrottledException.stream.
The snapshot when the navigator is popped is equal (the data) to the last emission.
You can see in the following demo that whenever I press the back button the dialog pops up again:
What could cause the StreamBuilder to rebuild itself when I press on the back button?
I had to change RootContainer to extend StatefulWidget instead of StatelessWidget.
I have no idea what's happening behind the scene, but it works! Any explanation would be nice.