Mimic iOS 13 fullscreen dialog - flutter

I noticed that in iOS 13 full screen dialog has changed, introducing a new slide from bottom animation.
Here is an example
Is it possible to mimic this behaviour with flutter? iOS animation it's not a simple slide from bottom but involves also the background page.
Looking throught flutter documentation I found this class but, without any example I can't understand how to use it or if it's what I'm searching.
Thanks

Update: Based on another answer by #VadimKo, I now understand that the stacking effect might also be desired. The answer linked to a package modal_bottom_sheet based on which I have updated my example
If I'm understanding your question right, you want to show a full screen dialog that slides up from the bottom and has UI similar to the one showed in your picture.
CupertinoFullscreenDialogTransition is really just two SlideTransitions stacked up so it's nothing special.
You could achieve something close to the posted images by using showGeneralDialog
In that, you could show anything using the combination of pageBuilder and transitionBuilder. It's very flexible and can even be used to show full routes on top of current route.
If you use CupertinoFullscreenDialogTransition as the pageBuilder it should achieve your goal. It's not required to provide a transitionBuilder since it's being performed by the pageBuilder implicitly.
The following example tries to mimic requested UI by using CupertinoApp, CustomScrollView and CupertinoSliverNavigationBar for the content of the dialog
Update: A transitionBuilder similar to the one provided by modal_bottom_sheet can be used to add the stacking effect.
Important code from the DartPad example:
showGeneralDialog(
barrierDismissible: true,
barrierLabel: 'Settings',
barrierColor: Colors.black,
context: context,
/// This would be slow but good to understand how transitions are working
transitionDuration: const Duration(seconds: 1),
/// Optionally provide the [transitionBuilder] to get the stacking effect
/// as of iOS 13
transitionBuilder: (context, animation, secondaryAnimation, child) {
/// The following transition widget was inspired from `modal_bottom_sheet` package
/// Some modifications have been made to remove certain limitations,
/// See the full DartPad example or take a look at `modal_bottom_sheet`
return _CupertinoModalTransition(
animation: animation,
child: child,
/// This renders the current widget behind the modal
/// Notice the use of [this], it is to make sure correct context is used
behindChild: this.build(this.context),
);
},
pageBuilder: (context, animation, secondaryAnimation) {
/// This is the simplest use case for [CupertinoFullscreenDialogTransition]
/// This provides the slide up and slide down transition effects
return CupertinoFullscreenDialogTransition(
primaryRouteAnimation: animation,
secondaryRouteAnimation: secondaryAnimation,
/// Content of your dialog
child: Container(),
linearTransition: true,
);
},
);
DartPad Full example : https://dartpad.dev/57de88ce8d64dff9d3e6fe0627a8b654
Update: The DartPad example works just like modal_bottom_sheet but without any need to make changes to existing code such as the requirement to use MaterialWithModalsPageRoute or to wrap current/preview routes in CupertinoScaffold both of which are provided by the same package.
Preview:
See the GIF preview: https://i.imgur.com/mZ77M62.gifv
Note: There is already showCupertinoDialog provided by the flutter team but it doesn't provide as much flexibility. It can however be used for normal small dialog popups that don't usually take full screen space.

You can always build your own widgets, however in this case you can use an existing package: Modal bottom sheet
you can also check some more existing flutter issues here: enter link description here

You can use this package cupertino_fullscreen_modal
CupertinoFullscreenModal.of(context).showModal(Widget child, onClose (popValue) {});

You can also try another already existing package Cupertino Stackview
CupertinoStackView(
true, //_isPrimary
"Page I", //_navigation
Scaffold(...), //_child
Colors.black, //_backgroundColor
{Key key,
isDismissible : true,
radius : Radius.circular(10.0)})

Related

Programmatically make modalBottomSheet dismissable in Flutter

I use showModalBottomSheet to render a bottom sheet with buttons (StatefulWidgetWithButtons). Once a button is pressed the state of the sheet changes and it gets re-rendered with different content.
I would like that depending on a certain state the sheet becomes not dismissable. I can achieve this using
showModalBottomSheet(
isDismissable: false
builder: (context) => StatefulWidgetWithButtons()
)
however what I want to achieve is that depending on a certain button pressed within StatefulWidgetWithButtons the isDismissable property changes to true (or false).
I don't know how to achieve this since I know I can change the StatefulWidgetWithButtons but that won't rebuild the bottom sheet.
I also don't want to close and show again the bottom sheet but change its dismissable behaviour while it is rendered
I was able to get this behaviour by wrapping the non-dismissible layout variant of the bottom sheet in a GestureDetector with vertical drag handler like so:
GestureDetector(
onVerticalDragUpdate: (_) {},
child: ...
This prevents the default modal bottom sheet drag handlers from taking action
If you want to learn more about this solution and how it works you can read about it here: https://stackoverflow.com/a/71622120/11676468
It definitely seems more like a workaround/hack but it looks like the only alternative is to implement a completely custom showModalBottomSheet from scratch

Flutter show double bottomsheet type design

I need to know what type of widget is this in flutter or how can create this. I know this question is irrelevant but I didn't find this so that's why I need to ask
You can see it's showing a round bottom sheet type thing and in the background show one more rounded bottom sheet. These types of things I see in every app now and need to design something similar any help how can I achieve this?
try modal_bottom_sheet:
showCupertinoModalBottomSheet(
context: context,
builder: (context) => Container(),
)

Half transparent screen on top of another full screen

I am trying to create a screen like below which will allow user to show few buttons on top of another screen . So basically it will be on top of another screen which can be seen from the half transparent screen of the top level screen. Not sure how to create it and which widget to use. Can someone please guide here. I am trying to do this using flutter to create android as well as ios app.
You are looking for the stack widget here, develop your first screen and another one which you want to put on top. Put both in stack widget so one can come on top of another one.
On the screen which should be on top, make the first half of it transparent (which can be attained in different ways, one of it would be to use a Card with elevation of 0).
The most accurate answer would be do use an an showModalBottomSheet which we expand from the button into the screen and will also color the screen darker. Example code could be following:
await showModalBottomSheet<void>(
isScrollControlled: true,
context: context,
backgroundColor: Colors.white,
builder: (BuildContext context) {
return Container(width: MediaQuery.of(context).size.width, height: 200);
},
)
With the current answer you would have to write the entire funtionality for it by yourself, which could be quite unnecessary when there is already a widget out there for exactly this case

How to show Snackbar without Context object in flutter?

There are many times where we would have had separation of concerns when it comes to UI code and business logic. This is reflected in most of the state management solutions that we use in Flutter.
In many of the state management solutions where the business logic is outside the view file ( widget file) , there are cases where we want to show the snackbar based on the logic in flutter.
But to show a Snackbar we first need a context object. I have used a NavigatorState to navigate without context. But I don't know if there is a way to show SnackBar without context.
Can someone provide a solution for this ?
Also it would be very helpful if you could provide a Utility method that manages the state internally and whenever user wants to show snackbar would just call that utility method from his logical part of code.
You can specify scaffoldMessengerKey as a property of MaterialApp and then ScaffoldMessenger can be directly used without BuildContext.
I think you can do the same way as navigatorKey.
ref: https://api.flutter.dev/flutter/material/MaterialApp/scaffoldMessengerKey.html
Check this answer for more details on how to implement this into your application, with some code examples.
You definitelly can show a piece of information without a context, something similar to a snackbar, however, it is not a snackbar.
If you use the package Get, you can navigate without context, open dialogs, snackbars or bottomsheets from anywhere in your code. However, the snackbars in particular have some issues.
As it doesn't check for a Scaffold, the snackbar is shown directly in the bottom of your screen. This means that if you have a BottomNavigationBar, it will be covered or partially covered by it.
It also means that if you have a FloatingActionButton, it won't be responsive to the snackbar position, as opossed to the normal snackbar.
So to sum up, with Get, you can have snackbars without context but you will have to make some sacrifices in your UI.
Example
final bottomSnackBar = GetBar(
isDismissible: false,
showProgressIndicator: true,
message: 'Processing...',
);
bottomSnackBar.show();
somethingAsync().then((_) => bottomSnackBar.hide());

How to make entire screen inactive (darken) under a popup widget in flutter (similar to showDialog)?

I have an "add" floating action button in Scaffold. When clicking the "add" floating action button, it will create two more floating action buttons above the original floating action button so that the user can choose which floating action button to click.
When the two more floating action buttons are active/popup, I want the entire screen to go blur/dark and inactive, similar to the effect to call showDialog(). So that only the three floating action buttons are active and all other screen parts are inactive and dark/blur.
And finally by clicking the inactive area, the two floating action buttons will be dismissed.
Thank you very much for your help.
I found two ways to achieve this.
With PopupRoute
I read flutter framework code and found out showDialog is actually using PopupRoute. Basically, this will create a new route and make the previous routepage inactive.
The simplest code is as follows:
class MyPopupRoute extends PopupRoute<void> {
#override
Color get barrierColor => Colors.black54;
#override
bool get barrierDismissible => true;
#override
String get barrierLabel => "Close";
#override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) => MyPopupPage();
#override
Duration get transitionDuration => const Duration(milliseconds: 300);
}
where MyPopupPage is the new popup widget.
If you want animations, you can override the method buildTransitions method. Simply check the API doc for more detail.
With Overlay
Thank #01leo very much for providing this way. The Flutter Challenge: Feature Discovery video has detail explanation on how to use it. Basically, just use Overlay.of(context).insert(overlayEntry); and the overlay is like a hidden stack on the top of the current page built-in.
At the time I am writing this answer, the code provided by the video author is not working in the latest fluter (dart 2). You have to wrap the overlay insert in a Timer such as Timer.run(() { Overlay.of(context).insert(calendarOverlay);}); to workaround the problem and make the code run.
By my findings, the reason why the author needs an async function call for overlay insert is because it couples the creation of overlay and the normal widget in a stateful widget. And when the state changes, the overlay insert will be called before building the child's widget and overlay needs to know the child's position but the child's widget is not created yet. If you don't want to async call overlay insert, you can simply decouple the creation of overlay and the corresponding normal widget. In such a way, you can simply call overlay insert normally. But with this sync way, you may not be able to find the normal widget position easily though.
(Btw, I use the word "normal widget" here, but it's not very correct. I haven't found a proper English word for it.)
I can't provide any code, but showDialog() and similar methods use the Overlay, integrated in Scaffold. It can be accessed by using Overlay.of(context). It essentially is a Stack around the whole Scaffold and you can insert items on top of everything.
For a more in-depth look into the Overlay and code examples I recommend watching this Flutter Challenge: Feature Discovery