I hope I can make this kind of pop-up effect similar to dropDownMenuButton. Is there any plugin or example that can be used for reference or help?
If you want a floating window i would suggest using a dialog.
To use a dialog you use a function and provide it with a context
This example should show a rounded corned white dialog with "YAY!" in the middle of it.
You close the dialog calling Navigator.of(context).pop() , and You could also use the align widget combined with padding to make it appear to the bottom, top, left, and right.
Touching on the backdrop of the dialog will also dismiss it.
void _showDialog(context) {
showDialog(
context: context,
builder: (BuildContext context) {
// return my custom widgets
return Center(
child: SizedBox(
width: 250.0,
height: 250.0,
child: Material( //Use material to use FlatButton, IconButton, InkWell, etc.
borderRadius: BorderRadius.all(Radius.circular(12.0)),
color: Colors.white,
child: Text('YAY!')
)));
},
);
}
Feel free to experiment.
I am using a card inside a dialog. It occupies full screen even though the child of the card has a container widget of fixed width and height.
I am using the below code:
showDialog(context: context, builder: (context)
{
return Card(
clipBehavior: Clip.antiAlias,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
elevation: 8.0,
child: Container(
width: MediaQuery.of(context).size.width * 0.80,
height: 300,
color: const Color(0xFF465A63)
),
);
});
Wrap the Card in a size-constraining widget like SizedBox, FractionallySizedBox or Container. Give it a certain size and position it on the screen using Center or Align.
By default the showDialog() method gives you the whole screen to compose a widget, not only the small window the AlertDialog() widget for example uses.
I am creating a new page route PopupRoute and using a Stack as the root of the new popup page. It works fine until I add Text to its children. Text will have two yellow lines underneath. I tried Material(child:Stack()) and Scaffold(child:Stack()). It can fix the yellow line issue, but it covers the entire screen and make the barrierDismissible not work.
Are there any other widgets can solve the Text yellow issues in my case?
You just need to wrap your Text widget inside a DefaultTextStyle widget. A DefaultTextStyle widget gets added implicitly by the Scaffold or Material widget.
DefaultTextStyle(
style: TextStyle(),
child: Text("This is a test"),
),
There might be a cleaner solution, but the first thing I thought of is wrapping Material inside of Align widget.
e.g.
showDialog(context: context, barrierDismissible: true, builder: (context) {
return Stack(alignment: Alignment.center, fit: StackFit.loose, children: <Widget>[
Container(width: 100, height: 100, color: Colors.blue),
Align(
child: Material(
type: MaterialType.transparency,
child: Text("TEXT"),
)
),
]);
});
I'm using a CustomPainter to draw a reveal animation that ends up covering the whole screen. The problem is that there are still elements that seem to be above my painter and thus stay visible.
My widget looks like that:
Material(
elevation: 10.0,
type: MaterialType.circle,
color: Colors.white,
child: GestureDetector(
onTap: reveal,
child: CustomPaint(
painter: CircularRevealButtonPainter(context, _fraction, backgroundColor: Colors.white),
child: child,
),
),
);
The reveal function starts animating _fraction which is used by the painter to increase the size of the circle until it covers the screen.
The visible element that is supposed to be painted over is at elevation 0.0, so that property doesn't seem to have any effect.
Is there another way I'm not aware of?
I have a home screen with a FAB and when it's pressed I want to display a dialog for user to input.
Currently I am using showDialog() with SimpleDialog.
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
title: NormalText('New Counter Item'),
contentPadding: EdgeInsets.fromLTRB(24.0, 0.0, 24.0, 24.0),
children: <Widget>[
Container(
...
)
],
);
}
);
But, I can't seem to customise almost anything with it (smaller, corner-curved and positioned lower on the screen). AlertDialog seems to be the same.
Is there anyway to customise those attributes?
return showDialog<void>(
barrierDismissible: true,
context: context,
builder: (BuildContext context) {
return new Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(0),
child: new Container(
height: 100,
width: MediaQuery.of(context).size.width,
color: Colors.purple,
child: new Column(
children: <Widget>[
new Text(
'custom dialog text',
style: new TextStyle(
fontSize: 14,
color: Colors.white,
),
),
],
),
),
)
],
);
},
);
hope this helps,
thanks
SimpleDialog and AlertDialog are meant to cater to a specific set of needs. They have certain levels of customization, but ultimately they are meant to just show simple pop-up dialogs that give the user some information and prompt for a dialog response (i.e. "Yes", "No", "Cancel", "Save", etc.).
If you want to have a more customizable pop-up dialog, you will need to create your own. On the plus side, though, it's really quite simple. Have the builder in showDialog return a Dialog widget with a child set to whatever you want:
showDialog(
context: context,
builder: (BuildContext cxt) {
return Dialog(
child: Container(
...
),
);
},
);
Obviously you are going to need to recreate things like the title bar and action bar, but you can either crack open the source code of SimpleDialog and AlertDialog and copy what they have there or you can roll your own solution.
Despite what the accepted answer says; there are ways to customise the SimpleDialog in the ways that you have requested.
Size
The SimpleDialog will grow in width/height depending on the child and how it is padded. The below code will generate a dialog of width 336 and height 300:
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
insetPadding: EdgeInsets.zero,
titlePadding: EdgeInsets.zero,
contentPadding: EdgeInsets.zero,
children: [
Container(
width: 300,
height: 300,
),
],
);
},
);
Not sure what the added 36 pixels to the width is; but this demonstrates that size can be customised.
Corners
Corners can be customised using the shape property. The below code shows a green border with a rounded edge of 4 pixels:
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(4.0),
side: BorderSide(
color: Colors.green,
),
),
/* ... */
);
},
);
Position
I've found that I can nudge the dialog up and down the page by using the insetPadding property. This defines the minimum amount of space required between the edge of the screen and the dialog. Although it's a bit cumbersome, if you knew the size of the screen and the size of the dialog, you could nudge the dialog's position with some simple math.
Given a screen height of 1920px, and a dialog height of 300px, the below code should place your dialog 100px from the top edge of your screen, rather than bang in the centre:
showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
insetPadding: EdgeInsets.only(bottom: 1520),
/* ... */
);
},
);
This is because I've requested a minimum padding between the bottom edge of the screen and the dialog; and the only position for the dialog to exist under this stipulation is nearer the top.
No. These are not designed to be customizable. They were made to respect Material Design principles in mind.
If you want a custom design, you can make your own modal based of Align and/or DecoratedBox
It's not as scary as you might expect.
You only need to clone Dialog.dart, and
replace the Center widget with an Align.
Of course also rename stuff; e.g. MyDialog, myShowDialog, MySimpleDialog.
Yep, it's that easy.
And if you're on a roll, how about adding the Align widget's alignment parameter as an extra...
You can actually modify it's position (only height) by adding a SingleChildScrollView() in the builder + a padding (for the offset from the top) as follows:
showDialog<String>(
context: context,
builder: (ctxDialog) =>
SingleChildScrollView(
child: Padding(
padding: EdgeInsets.only(top: 150.0),
child: AlertDialog()
)
)
);
Here is a clean solution, If for some reason you have a TextField/TextFormField and in there you have a onsubmit property then you can follow:
onSubmit: () {
showDialog(
context: context,
builder: (context){
return WillPopScope(
onWillPop: () { return Future(() => false); }, // this will prevent going back
child: AlertDialog(
content: Row(
children: [
progressWidget(),
Container(margin: EdgeInsets.only(left: 10.0),child:Text("Loading" )),
],),
)
);
}
);
yourCallToMethod.whenComplete((){
Navigator.of(context).pop();
});
},
BENEFIT?
When the showAlert is shown if someone tap on the screen randomly or aggressively then the screen goes back. This prevents that behavior and only closes the showAlert when your function completes.
:- we can change vertical position of dialog boxes by give bottom
insetPadding like
insetPadding: EdgeInsets.only(bottom: XX);
:- And horizontal position by Horizontal padding or left
insetPadding: EdgeInsets.symmetric(horizontal:XX);
or
insetPadding: EdgeInsets.only(left: XX,right:YY);
I found the answer to it here. Thanks to #CopsOnRoad
Using showGeneralDialog
Scaffold(
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
showGeneralDialog(
context: context,
barrierColor: Colors.black54,
barrierDismissible: true,
barrierLabel: 'Label',
pageBuilder: (_, __, ___) {
return Align(
alignment: Alignment.bottomLeft,
child: Container(
color: Colors.blue,
child: FlutterLogo(size: 150),
),
);
},
);
},
),
)
Solved that with wrapping dialog body in Stack and Positioned
Stack(
children: [
Positioned(
left: 100, // left coordinate
top: 100, // top coordinate
child: YOUR_DIALOG....