How to customize a dialog's position, size and background? - flutter

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....

Related

height of cards base on widgets height flutter

I want to set the height for my cards based on the height of the widgets in it.
I use globalKey and set it in my widget but return null.
can anyone help me how can I do that?
final GlobalKey _Key = GlobalKey();
showModalBottomSheet(
context: context,
useRootNavigator: true,
isScrollControlled: true,
isDismissible: true,
enableDrag: true,
builder: (context) {
return Container(
key : _key,
child: ListView(
shrinkWrap: true,
padding: EdgeInsets.zero,
children: [
PressWidget(),
PaddingButtonCard(),
],
),
);
},
);
when I print _Key.currentContext?.findRenderObject().size , return null.
A Widget like a card should automatically wrap it's contents, so unless the contents have an unconstrained height (like a ListView or Expanded widget), you shouldn't need measuring or such techniques to achieve this.
Try, as a test, putting a Container with a set height inside your Card, and observe how the card automatically sizes itself:
Card(
child: Container(
height: 40,
width: double.maxFinite,
color: Colors.purple,
child: Text('Purple Card'),
),
),

make photo bigger when click on flutter

how to make the picture zoomable when the photo is clicked, here's the code I made to display the image
Column(
children: [
image11 != null
? Image.file(
image11,
width: 50,
height: 50,
fit: BoxFit.cover,
)
: Text(" Bagian Belakang"),
Container(
margin: const EdgeInsets.fromLTRB(14, 5, 0, 0),
child: RaisedButton(
padding: EdgeInsets.all(10),
onPressed: () {
pickImage11(ImageSource.camera);
},
child: Icon(Icons.camera),
),
),
],
),
Taking inspiration from this answer Hero animation with an AlertDialog
You can use a Hero widget combined with a PageRouteBuilder to imitate a zoom feature:
Navigator.of(context).push(
PageRouteBuilder(
opaque: false,
barrierDismissible:true,
pageBuilder: (BuildContext context, _, __) {
return Hero(
tag: "zoom",
child: Image.file(...),
);
}
)
);
EDIT: I found barrier dismissable not working and found the solution here: Flutter SizeTransition and PageRouteBuilder not working
You will have to wrap the Hero widget with a defined width and height to get the optimum zoom level.

How to create a form with add more field in flutter using flutter_form_builder?

Flutter Web
So I have a button called add tags which opens up a modal. The Modal has only one text field and two buttons called add another tag and submit.
Now what I want to do is when the user clicks the add another tag button the app will generate another text field.
I've already seen some videos and read the documentation but since I need to work on a modal and the modal has defined size I'm not sure how to handle issues like
What happens if the user adds a lot of tags. How can I make the modal scrollable?
I'm new to flutter_form_builder so I'm not sure if the modal can handle it or not.
Here's my code:
final _formKey = GlobalKey<FormBuilderState>();
Future buildAddTagsForm(BuildContext context,
{Function()? notifyParent}) async {
return await showDialog(
barrierDismissible: false,
barrierColor: Colors.black.withOpacity(0.5),
context: context,
builder: (context) {
var screen = MediaQuery.of(context).size;
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
content: SingleChildScrollView(
child: Container(
height: screen.height / 2,
width: screen.height > 650 ? 600.00 : screen.height * 1,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: FormBuilder(
key: _formKey,
autovalidateMode: AutovalidateMode.onUserInteraction,
child: Column(
crossAxisAlignment: CrossAxisAlignment.end,
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(
Icons.cancel_presentation_rounded,
),
),
],
),
SizedBox(
height: 10,
),
FormBuilderTextField(
name: 'Tag Name',
decoration: InputDecoration(labelText: 'Tag name'),
validator: FormBuilderValidators.compose([
FormBuilderValidators.required(context),
]),
),
SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
MaterialButton(
color: CustomColors.buttonColor,
child: Text(
"Add another tag",
style: TextStyle(
color: Colors.white,
),
),
onPressed: () {},
)
],
),
SizedBox(
height: 10,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
MaterialButton(
color: CustomColors.buttonColor,
child: Text(
"Submit",
style: TextStyle(
color: Colors.white,
),
),
onPressed: () {},
)
],
),
],
),
),
),
),
),
);
},
);
},
);
}
I'm assuming by "modal" we're talking about the AlertDialog here:
return AlertDialog(
content: SingleChildScrollView(
By using SingleChildScrollView as the AlertDialog content:, we can have any size / any number of text fields we like in the dialog. If their number are too many for the height of dialog inside our screen, the content will scroll.
Although, its immediate child Container with height prevents the SingleChildScrollView from doing its magic:
return AlertDialog(
content: SingleChildScrollView(
child: Container(
height: screen.height / 2,
I think the above AlertDialog would not scroll because it would never be big enough to need to scroll. Plus, any fields added that combine to be taller than that specified height (screen.height / 2) will cause an overflow warning and be cutoff visually.
So to answer question #1: "What happens if the user adds a lot of tags. How can I make the modal scrollable?"
using SingleChildScrollView is the right idea
lets swap the position of the Container with height and the SingleChildScrollView and this should allow the dialog to grow & scroll as needed as columns in FormBuilder increase
Your question #2: "I'm new to flutter_form_builder so I'm not sure if the modal can handle it or not."
flutter_form_builder shouldn't affect how SingleChildScrollView works
Example
Here's a partial example of an AlertDialog with scroll view content: that can grow in number.
Widget build(BuildContext context) {
return Container(
height: 300,
child: AlertDialog(
content: SingleChildScrollView(
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: items,
),
),
),
actions: [
OutlinedButton(
child: Text('Add Row'),
onPressed: _incrementCounter
)
]
),
);
}
The complete example runnable in DartPard is here. (Add a 6 or 7 rows and then scroll the content.)
Warning
There's a gotcha with using the above AlertDialog inside a sized Container. That Container with height is not enough to constrain the AlertDialog size.
Your showDialog builder: (that pushes the AlertDialog into existence) must provide additional constraints in order for the sized Container to have constraints to size itself within. Without these constraints, the AlertDialog will grow until it matches the device viewport size. I believe this is a quirk with how showDialog is written, since I'm guessing it's a modal layer on top of the current stack of routes. (Someone can correct me if I'm wrong.) It's only constraint is the physical device, but nothing else. By wrapping builder:'s output with a constraining widget (such as Center) the output will be able to size itself.
To see this in action, remove the Center widget from the full example above an re-run it. The dialog will grow to fill the screen when adding rows instead of being at max 300px in height.
child: OutlinedButton(
child: Text('Open Dialog'),
onPressed: () => showDialog(
context: context,
builder: (context) => Center(child: MyDialog())
),
)

Flutter Simple Dialog content going off the screen

I have a dialog I am trying to wrap the content in the dialog however I am having few problems
1)Use of wrap does not guarantee that content is in the alert dialog box
2)alignment of content is not center.
I have tried all possible alignment and it does not work.
While using column stretch the widget I thought maybe using wrap will work . But it does not.
Any solution?
With Column
With Colored Container in a wrap to check the issue and with size box with defined width of display * 0.25 so that text does not go away from screen
Code
showDialog(
barrierDismissible: false,
barrierColor: Colors.black26,
context: context,
builder: (context) {
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
contentPadding: EdgeInsets.all(20),
content: Wrap(
direction: Axis.vertical,
alignment: WrapAlignment.spaceAround,
runAlignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
runSpacing: 10,
children: [
Lottie.asset(
Constants.location_anim,
height: displaySize.height * 0.25,
repeat: true,
reverse: true,
animate: true
),
Text(locationMsgTextView,softWrap: true,),
getLocationDeniedWidget(context,state),
],
),
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(20)),
);
},
);
});

Remove Padding on CupertinoSliverNavigationBar

I am trying to use CupertinoSliverNavigationBar, actually it's great, but for some reason I can't place the trailing right on the end of navigation bar. I looked up and I (guess, I) found that there's Padding inside it
this is my code
new CupertinoPageScaffold(
child: new CustomScrollView(
slivers: <Widget>[
new CupertinoSliverNavigationBar(
largeTitle: new Text('Tasks'),
trailing: new CupertinoButton(
child: new Icon(AdditionalCupertinoIcons.compose, size: 32.0),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return new CupertinoAlertDialog();
});
},
padding: EdgeInsets.all(0.0),
),
)
],
),
),
Sadly, no can-do.
Looking at this line of source code, you can see that they are using a Padding at the end, which is _kNavBarEdgePadding, i.e. 16.0. Same for the start.
This means that with the CupertinoSliverNavigationBar you will not be able to remove that Padding because there is no access point to change it. You will have to create your own widget for that.
The _CupertinoPersistentNavigationBar widget contains the Padding and is used by CupertinoSliverNavigationBar, as can be seen here and for completion here.
There is an easy way to move a widget on the screen:
Widget _adjustNavigationBarButtonPosition(Widget button, double x) {
if (button == null) return null;
return Container(
transform: Matrix4.translationValues(x, 0, 0),
child: button,
);
}
Wrap your CupertinoButton with this method and specify an offset. To remove the padding completely, the offset should be 16.0.
You can use Matrix4.translationValues to move a child within the container. In your case x Matrix4.translationValues(12, 0, 0), should be positive to move the trailing to the right.
new CupertinoPageScaffold(
child: new CustomScrollView(
slivers: <Widget>[
new CupertinoSliverNavigationBar(
largeTitle: new Text('Tasks'),
trailing: Container(
transform: Matrix4.translationValues(12, 0, 0),
child : CupertinoButton(
child: new Icon(AdditionalCupertinoIcons.compose, size: 32.0),
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return new CupertinoAlertDialog();
});
},
)
),
)
],
),
),