I want to display some option in the bottom of Flutter AlertDialog. As you can see
If I understand correctly you can use the showDialog component which lays behind the AlertDialog with a nested Column. For a greyed out background ou can use Opacity with a Container:
showDialog(
context: context,
builder: (context) {
return Opacity(
opacity: 0.8, // some opacity
child: Container(
// container to set color
color: Colors.grey,
child: Column(
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.end,
children: [
RaisedButton(
onPressed: null,
), // replace with your buttons
RaisedButton(
onPressed: null,
),
]
)
)
);
}
);
Simple way: you can use padding
showDialog<String>(
context: context,
barrierDismissible: true,
builder: (BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top:300.0),
child: //AlertDiloag / CupertinoAlertDialog
);
},
);
Related
I am using an alert box where I am getting the image from gallery of the user, but the updated image is not getting displayed.
When I close the alert box and again open the alert box, then it's getting displayed. I am using provider package to handle the data.
Here is a video of what I am getting now
Here is my code:
child: ChangeNotifierProvider<MyProvider>(
create: (context) => MyProvider(),
child: Consumer<MyProvider>(
builder: (context, provider, child) {
return Column(
children: [
ElevatedButton(
onPressed: () {
showDialog(
barrierDismissible: true,
context: context,
barrierColor: Colors.black.withOpacity(0.5),
builder: (ctx) => AlertDialog(actions: <Widget>[
----> // alert box styling
Expanded(
child: Column(
children: [
CircleAvatar(
backgroundColor:
Colors.transparent,
radius: 175,
child: ClipOval(
child: provider
.image !=
null
? Image.network(
provider.image
.path,
height: 200,
)
: Image.asset(
'assets/profile.webp',
width: 250.0,
height: 250.0,
fit: BoxFit
.cover,
),
)),
Row(
mainAxisAlignment:
MainAxisAlignment
.spaceBetween,
children: <Widget>[
ElevatedButton(
onPressed: () async {
var image = await ImagePicker()
.pickImage(
source: ImageSource
.camera);
provider.setImage(
image);
},
child: Text(
'Use camera',
style: t3b,
),
),
},
child: const Text('Click me ')),
],
);
},
),
),
),
);
}
}
class MyProvider extends ChangeNotifier {
var image;
Future setImage(img) async {
image = img;
notifyListeners();
}
I am also facing the same issue in mobile development then I know we have to rebuild the whole dialog and then it will work well
showDialog(
context: context,
builder: (BuildContext context) {
int selectedRadio = 0; // Declare your variable outside the builder
return AlertDialog(
content: StatefulBuilder( // You need this, notice the parameters below:
builder: (BuildContext context, StateSetter setState) {
return Column( // Then, the content of your dialog.
mainAxisSize: MainAxisSize.min,
children: List<Widget>.generate(4, (int index) {
return Radio<int>(
value: index,
groupValue: selectedRadio,
onChanged: (int value) {
// Whenever you need, call setState on your variable
setState(() => selectedRadio = value);
},
);
}),
);
},
),
);
},
);
Use a StatefulBuilder in the content section of the AlertDialog. Even the StatefulBuilder docs actually have an example with a dialog.
What it does is provide you with a new context, and setState function to rebuild when needed.
also sharing the reference I used for this: Reference for solving this same
Safearea() does not wrap the showModalBottomSheet properly. I need to show the modal under the status bar.
class ModalBottomSheet {
static void renderModalBottomSheet(BuildContext context, Widget widget) {
showModalBottomSheet(
isScrollControlled: true,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.vertical(
top: Radius.circular(border2),
),
),
context: context,
builder: (BuildContext context) {
return SafeArea(
child: Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
child: widget,
),
);
},
);
}
}
I have tried the following solutions but it still doesn't work properly
MediaQuery.of(context).padding.top
MediaQueryData.fromWindow(WidgetsBinding.instance.window).padding.top
Update:
I managed to solve it this way.
add this to the bottomsheet
backgroundColor: Colors.transparent,
and padding top
top: MediaQuery.of(context).padding.top,
full code:
class ModalBottomSheet {
static void renderModalBottomSheet(BuildContext context, Widget widget) {
showModalBottomSheet(
isScrollControlled: true,
backgroundColor: Colors.transparent,
context: context,
builder: (_) {
return SafeArea(
child: Padding(
padding: EdgeInsets.only(
top: MediaQuery.of(context).padding.top,
bottom: MediaQuery.of(context).viewInsets.bottom,
),
child: widget,
),
);
},
);
}
}
your child widget can have the border radius and colors instead.
open keyboard
closed keyboard
Try this. If it doesn't work, refer this page
showModalBottomSheet<void>(
context: context,
builder: (BuildContext context) {
return SafeArea(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[...
you should get MediaQuery.of(context).viewPadding.top before showModalBottomSheet and pass it to sheet inside, then use EdgeInsets.top inside the sheet.
I am using a library for a calendar, https://github.com/benznest/flutter_rounded_date_picker, but I think this is a Flutter question and doesn't have to do with the library.
I copied all the files into my project, to be able to style freely.
However, I cannot remove the background black transparency that comes after opening the calendar.
Here is the relevant code (I believe this is the relevant code)
final Dialog dialog = Dialog(
child: OrientationBuilder(builder: (BuildContext context, Orientation orientation) {
assert(orientation != null);
final Widget header = FlutterRoundedDatePickerHeader(
selectedDate: _selectedDate,
mode: _mode,
onModeChanged: _handleModeChanged,
orientation: orientation,
era: widget.era,
borderRadius: widget.borderRadius,
imageHeader: widget.imageHeader,
description: widget.description,
fontFamily: widget.fontFamily,
style: widget.styleDatePicker);
switch (orientation) {
case Orientation.portrait:
return Container(
decoration: BoxDecoration(
color: backgroundPicker,
borderRadius: BorderRadius.circular(widget.borderRadius),
),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
header,
if (widget.height == null)
Flexible(child: picker)
else
SizedBox(
height: widget.height,
child: picker,
),
actions,
],
),
);
case Orientation.landscape:
return Container(
decoration: BoxDecoration(
color: backgroundPicker,
borderRadius: BorderRadius.circular(widget.borderRadius),
),
child: Row(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Flexible(flex: 1, child: header),
Flexible(
flex: 2, // have the picker take up 2/3 of the dialog width
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Flexible(child: picker),
actions,
],
),
),
],
),
);
}
return null;
}),
);
I tried adding
final Dialog dialog = Dialog(
backgroundColor: Colors.transparent
but it didn't work
I also tried replacing Dialog with Material, and put a bounded container inside,
Material(
color: Colors.transparent,
shadowColor: Colors.transparent,
child: Align(
but the black transparency in the background of the calendar does not go away.
How can I achieve this?
Thank you
This is how it is called
void _handleDateChange() async {
final date = await showRoundedDatePicker(
context: context,
initialDate: DateTime.now(),
firstDate: someDateTime,
lastDate: someOtherDateTime,
)
}
no black screen now.
You need barrierColor: Colors.transparent in showDialog function call
and barrierDismissible: true change this if you want to block outside click dismiss dialog -> false.
showAlertDialog(BuildContext context) {
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return dialog;
},
barrierDismissible: true,
barrierColor: Colors.transparent,
);
}
Also there is a shadow for dialog if you want to remove that also.
final Dialog dialog = Dialog(
...
elevation: 0,
);
there will not be any shadow or any backdrop.
It seems like the package limit. (flutter_rounded_date_picker) 1.0.5+1
Inner showRoundedDatePicker source, it call showDialog at the end (leave barrierColor value null)
Future<DateTime> showRoundedDatePicker(
...
return await showDialog<DateTime>(
context: context,
barrierDismissible: barrierDismissible,
builder: (_) => Theme(data: theme, child: child),
);
}
Inside showDialog, it will set barrierColor to black54 if it is null:
Future<T?> showDialog<T>({
...
return showGeneralDialog(
...
barrierColor: barrierColor ?? Colors.black54,
...
);
}
You can do as follow:
Add request to the package provider in github and wait for the update
Find another data picker package
Make your own custom date_picker
I am showing a bottom sheet with showModalBottomSheet like so:
showModalBottomSheet(
isScrollControlled: true,
context: context,
backgroundColor: Colors.transparent,
builder: (BuildContext context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Container(
height: MediaQuery.of(context).size.height * .90,
width: double.infinity,
child: Column(
children: [
Expanded(
child: PostCreate(isImageType: isImageType)
),
Padding(
padding: const EdgeInsets.fromLTRB(20, 0, 0, 20),
child: Align(
alignment: Alignment.bottomLeft,
child: IconButton(
onPressed: () {
setState(() {
isImageType = true;
});
},
icon: Icon(Icons.attach_file_rounded),
)
),
)
],
),
);
}
);
}
);
The PostCreate widget contains a column with a * form (single input) and a section for adding the images. When the keyboard is not visible the attach_file_rounded Icon is where you would expect (bottom left), but when the input is focused and the keyboard is visible, the icon is hidden behind the keyboard. I'm not concerned about the code in PostCreate because if I change it to just a form/input in Expanded:
Expanded(
child: Form(
child: TextFormField(
autofocus: true,
)
)
)
I have the same exact problem. What's the way for me to align something on the bottom left of a bottom sheet that will dynamically sit above the keyboard when it is active? Another thing to note, is that I do want the PostCreate widget to expand, allowing room for certain things (like the attach_file icon) on the bottom of the sheet. That is all working as expected, I just need it to adjust with the keyboard.
I figured this out by adding padding: MediaQuery.of(context).viewInsets, to the Padding widget around the Align/IconButton widgets.
Padding(
padding: MediaQuery.of(context).viewInsets,
child: Align(
alignment: Alignment.bottomLeft,
child: IconButton(
onPressed: () {
setState(() {
isImageType = true;
});
},
icon: Icon(Icons.attach_file_rounded),
)
),
)
I built an AlertDialog to display Loading while i'm authenticating the user and when it finishes i pop it.
Widget loadingDialog = new AlertDialog(
content: new Row(
children: <Widget>[
new CircularProgressIndicator(),
Padding(
padding: const EdgeInsets.only(left: 8.0),
child: new Text("Loading..."),
),
],
),);
But, if the user taps outside the Dialog it closes. So when the auth finishes, it will still pop something (i guess the scaffol), breaking the app.
How can i make Dialog not closable?
There is a property inside showDialog called barrierDismissible. Setting this value to false will make your AlertDialog not closable by clicking outside.
showDialog(
...
barrierDismissible: false,
...
To prevent dismissing of dialog on press of a back button, you should also wrap your AlertDialog (or any other widget) inside a WillPopScope.
showDialog(
context: context,
barrierDismissible: false, // <-- Set this to false.
builder: (_) => WillPopScope(
onWillPop: () async => false, // <-- Prevents dialog dismiss on press of back button.
child: AlertDialog(...),
),
);
// User Defined Function
void _showloding() {
// flutter defined function
showDialog(
barrierDismissible: false, // JUST MENTION THIS LINE
context: context,
builder: (BuildContext context) {
// return object of type Dialog
return AlertDialog(
content: Padding(
padding: const EdgeInsets.all(20.0),
child: Container(height: 100,width: 100,child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(child: SizedBox(height: 50,width: 50,child: CircularProgressIndicator())),
Padding(
padding: const EdgeInsets.only(top: 20),
child: Center(child: Text("Processing")),
)
],
)),
)
);
},
);
}
If you want to prevent dialog close when back button pressed then refer below code. You need to wrap the AlertDialog in WillPopScope widget and make onWillPop property value with function which return Future.value(false).
showDialog(
barrierDismissible: false, //this will prevent popup closing when touch outside of popup
context: context,
builder: (BuildContext context) {
return WillPopScope( // Wrap in WillPopScope widget
onWillPop: () => Future.value(false), //this line will prevent popup closing when back button of phone press
child:AlertDialog(
title: new Text("Alert Title"),
content: new SingleChildScrollView(
child: Container(),),
actions: [
new FlatButton(
child: new Text("Close"),
onPressed: () {
},
),
],
)
)
},
);