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,
)
Related
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.
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
));
}
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
I'm a beginner to Flutter, and in my current (first) project I have an alert that I want to pop up before the next bit of code runs.
If I use await I have found that it then requires the user to tap on the screen (outside the bounds of the alert) in order for the program to continue. Is there any way to just make sure the alert is present before proceeding without requiring the tap?
Here is my alert method:
myAlert(BuildContext context) {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return new AlertDialog(
title: Text('Some text'),
);
},
);
}
I call the method and then in the next line call another method which does some intensive computations:
myAlert(context);
compute();
Both methods are called on the press of a button (I don't know if this would be relevant in any way, so just putting it out there).
I want compute() to be called only after the alert appears. As of right now, compute() begins running before the alert pops up.
Thanks!
This is a bit confusing, but if you want compute to run when creating the dialog, run it inside the builder (a better option might be to create a separate widget and do it in his initState).
myAlert(BuildContext context) {
return showDialog<void>(
context: context,
builder: (BuildContext context) {
return new MyAlertDialog();
},
);
}
my_alert_dialog.dart
class MyAlertDialog extends StatefulWidget {
#override
_MyAlertDialogState createState() => _MyAlertDialogState();
}
class _MyAlertDialogState extends State<MyAlertDialog> {
#override
void initState() {
compute()//HERE u can du your compute
super.initState();
}
#override
Widget build(BuildContext context) {
return //Build here your Dialog Content...
}
}
If you wanna wait for the dialog close and then execute your compute, use await.
myAlert(BuildContext context) async{
return await showDialog<void>(
context: context,
builder: (BuildContext context) {
return new AlertDialog(
title: Text('Some text'),
);
},
);
}
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.