I want to make a AlertDialog which is included a slider (especially SfRangeSlider()).
My AlertDialog Image:
There is a problem with the height of AlertDialog.
My question is how to reduce the dialog size including the SfRangeSlider().
My _showDialog() as below:
void _showDialog() async {
await showDialog<String>(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text('총톤수'),
content: SfRangeSlider(
min: 0.0,
max: 100.0,
values: _values,
interval: 10,
showTicks: false,
showLabels: true,
enableTooltip: true,
minorTicksPerInterval: 1,
onChanged: (SfRangeValues values) {
setState(() {
_values = values;
});
},
),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context, 'Cancel'),
child: const Text('Cancel'),
),
TextButton(
onPressed: () => Navigator.pop(context, 'OK'),
child: const Text('OK'),
),
],
),
);
}
Thank you.
You can wrap SfRangeSlider with SizedBox and provide height.
void _showDialog() async {
await showDialog<String>(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text('총톤수'),
content: SizedBox(
height: x, // x= hard-coded value or you can use MediaQuery.of(context).size.height *.5 ,,50% height
child: SfRangeSlider(
min: 0.0,
If you don't want to use static height: you can wrap your SfRangeSlider with Column and set its mainAxisSize to min:
showDialog<String>(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text('총톤수'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: [
SfRangeSlider(
min: 0.0,
max: 100.0,
values: _values,
interval: 10,
showTicks: false,
showLabels: true,
enableTooltip: true,
minorTicksPerInterval: 1,
onChanged: (SfRangeValues values) {
setState(() {
_values = values;
});
},
),
],
),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context, 'Cancel'),
child: const Text('Cancel'),
),
TextButton(
onPressed: () => Navigator.pop(context, 'OK'),
child: const Text('OK'),
),
],
),
);
Related
The slider works fine outside the AlertDialog, but when I insert the slider into the content inside the AlertDialog, the display works fine, but it doesn't scroll. How do I solve this?
This is Image that AlertDialog with SfSlider
This is my code:
double _value = 40.0;
SfRangeValues _values = SfRangeValues(15.0, 35.0);
_showDialog() async {
await showDialog<String>(
context: context,
builder: (BuildContext context) => AlertDialog(
title: const Text('총톤수'),
content: SizedBox(
width: 500,
height: 80,
child: SfRangeSlider(
min: 0.0,
max: 50.0,
values: _values,
interval: 10,
showLabels: true,
enableTooltip: true,
onChanged: (SfRangeValues values){
setState(() {
_values = values;
});
},
),
),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context, 'Cancel'),
child: const Text('Cancel'),
),
TextButton(
onPressed: () => Navigator.pop(context, 'OK'),
child: const Text('OK'),
),
],
),
);
This is GestureDetector:
GestureDetector(
onTap: () {
return _showDialog();
},
Thank you.
here is the problem, since alertdialog is a separate context, you have to wrap it with stateful and make it setstate, I edited your code.
_showDialog() async {
await showDialog<String>(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(builder: (context, setState2) {
return AlertDialog(
title: const Text('총톤수'),
content: SizedBox(
width: 500,
height: 80,
child: SfRangeSlider(
min: 0.0,
max: 50.0,
values: _values,
interval: 10,
showLabels: true,
enableTooltip: true,
onChanged: (SfRangeValues values) {
setState2(() {
_values = values;
});
},
),
),
actions: <Widget>[
TextButton(
onPressed: () => Navigator.pop(context, 'Cancel'),
child: const Text('Cancel'),
),
TextButton(
onPressed: () => Navigator.pop(context, 'OK'),
child: const Text('OK'),
),
],
);
});
});
}
I have been trying to make a dialog popup when pressing a popupmenubutton, however it does not seem to work, I run the app in debug mode through chrome as my Laptop is unable to run in debug mode through androud studio emulator.
child: Scaffold(
resizeToAvoidBottomInset: true,
backgroundColor: Color.fromRGBO(31, 31, 47, 1),
appBar: AppBar(
actions: [
PopupMenuButton<String>(
padding: EdgeInsets.all(0),
onSelected: (value) {
print(value);
},
itemBuilder: (BuildContext context) {
return [
PopupMenuItem(
child: Text('Cancel'),
onTap: () {BackdropFilter(
filter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
child: Dialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(15.0)),
backgroundColor: Color(Color.getAlphaFromOpacity(0.5)),
child: _dialogContent(),
)
);
},
),
];
},
),
], ),
Widget _dialogContent() {return SimpleDialog(
title: Text('Enter Cancel Code'),
children: <Widget>[
// TextFormField()
ElevatedButton(
onPressed: () => Navigator.pop(context, false),
child: Text('Okay')),
],);}
}
the reason why I doesn't work is because you didn't specify a value to your popupMenuItem thats why your onSelected property dont know what to do when you tapped on an item, so to make it work you need to do like so
PopupMenuButton<int>(
padding: const EdgeInsets.all(0),
onSelected: (value) {
if (value == 0) {
showDialog(context: context, builder: (context) => _dialogContent,);
}
},
itemBuilder: (BuildContext context) {
return [
const PopupMenuItem<int>(
value: 0,
child: Text('Show dialog'),
),
];
},
),
:
if you want to use the onTap property of the PopupMenuItem, you need to delay your showDialog because when you call the onTap, it is triggering the Navigator.of(context).pop(). So it looks like nothing is happening when you try to show dialog because its being popped immediately. So to make it work, you need to do it like so:
PopupMenuButton<int>(
padding: const EdgeInsets.all(0),
itemBuilder: (BuildContext context) {
return [
const PopupMenuItem<int>(
value: 0,
child: Text('Show dialog'),
onTap: ()=> Future.delayed(Duration(milliseconds:1),(){
showDialog(context:context, builder: (context)=> _dialogContent)
})
),
];
},
),
I try to manage a state "playerList" in two screens:
The code below shows how the provider was built
class PlayerList with ChangeNotifier {
List<Player> _playerList = [];
List<Player> get playerList {
return [..._playerList];
}
void addPlayer(Player player) {
_playerList.add(player);
notifyListeners();
}
void deletePlayer(int index) {
_playerList.removeAt(index);
notifyListeners();
}
}
In screen 1, everything works perfect. However, when I do the same, but then within an AlertDialog, the updated value only shows after closing the dialog and opening it again.
The code below shows the relevant part of the build method.
#override
Widget build(BuildContext context) {
PlayerList _playerListData = Provider.of<PlayerList>(context);
List<Player> _playerList = _playerListData.playerList;
return WillPopScope(
onWillPop: () async => showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(
'Are you sure you want to leave? The current game will be lost.'),
actions: <Widget>[
ElevatedButton(
child: Text('Yes'),
onPressed: () => Navigator.of(context).pop(true)),
ElevatedButton(
child: Text('No'),
onPressed: () => Navigator.of(context).pop(false)),
])),
child: Scaffold(
backgroundColor: Color(0xFF6ca0dc),
body: Center(
child: Column(children: [
_playChallenge(_playerList),
]),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Player List'),
content: Column(mainAxisSize: MainAxisSize.min, children: [
Container(
height: MediaQuery.of(context).size.height *
0.5, // Change as per your requirement
width: MediaQuery.of(context).size.width *
0.5, // Change as per your requirement
child: ListView.builder(
shrinkWrap: true,
itemCount: _playerList.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(
_playerList[index].name,
style: Theme.of(context).textTheme.headline6,
),
trailing: IconButton(
icon: Icon(Icons.delete),
color: Theme.of(context).errorColor,
onPressed: () =>
_playerListData.deletePlayer(index),
));
},
),
),
How can I solve this issue?
I solved the problem by adding a StatefulBuilder and using the Provider.of inside the statefulbuilder. See:
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () async => showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text(
'Are you sure you want to leave? The current game will be lost.'),
actions: <Widget>[
ElevatedButton(
child: Text('Yes'),
onPressed: () => Navigator.of(context).pop(true)),
ElevatedButton(
child: Text('No'),
onPressed: () => Navigator.of(context).pop(false)),
])),
child: Scaffold(
backgroundColor: Color(0xFF6ca0dc),
body: Center(
child: Column(children: [
_playChallenge(Provider.of<PlayerList>(context).playerList),
]),
),
floatingActionButton: FloatingActionButton(
onPressed: () {
showDialog(
context: context,
builder: (BuildContext context) {
return StatefulBuilder(builder: (context, setState) {
PlayerList _playerListData =
Provider.of<PlayerList>(context);
List<Player> _playerList = _playerListData.playerList;
return AlertDialog(
title: Text('Player List'),
content:
Column(mainAxisSize: MainAxisSize.min, children: [
Container(
height: MediaQuery.of(context).size.height *
0.5, // Change as per your requirement
width: MediaQuery.of(context).size.width *
0.5, // Change as per your requirement
child: ListView.builder(
shrinkWrap: true,
itemCount: _playerList.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(
_playerList[index].name,
style:
Theme.of(context).textTheme.headline6,
),
trailing: IconButton(
icon: Icon(Icons.delete),
color: Theme.of(context).errorColor,
onPressed: () =>
_playerListData.deletePlayer(index),
));
},
),
),
I'm new in flutter. I want to adjust the dimensions and other properties like background color of the CupertinoAlertDialog. I have searched in the documents and tried some properties but didn't work. For background color example, I have tried to put it into a Container and set its color. Definitely it didn't work. So how can I achieve it? Thanks in advance.
Container(
color: Colors.red,
child: CupertinoAlertDialog(
title: Text('dropOut'), //对话框标题
content: SingleChildScrollView(
),
actions: [
CupertinoDialogAction(
child: Text('cancel'),
onPressed: () {},
),
CupertinoDialogAction(
child: Text('OK'),
onPressed: () {},
),
],
),
),
Edited: I tried the method suggested by #Salim Murshed, but it didn't seem work so well. here is my code and the display!
Widget build(BuildContext context) {
// TODO: implement build
return MaterialApp(
home: Scaffold(
body: RaisedButton(
child: Text("Pick Me !!!"),
onPressed: () {
showDialog(
context: context,
builder: (_) => Center(
child: Container(
width: 270, height: 140,
color: Colors.red,
child: CupertinoAlertDialog (
title: new Text("Material Dialog"),
content: new Text("Hey! I'm Coflutter!"),
actions: <Widget>[
FlatButton(
child: Text('Close me!'),
onPressed: () {
Navigator.pop(_);
},
)
],
),
),
));
},
)
),
);
}
You can check the below code.
RaisedButton(
child: Text("Pick Me !!!"),
onPressed: () {
showDialog(
context: context,
builder: (_) => new AlertDialog(
title: new Text("Material Dialog"),
content: new Text("Hey! I'm Coflutter!"),
actions: <Widget>[
FlatButton(
child: Text('Close me!'),
onPressed: () {
Navigator.pop(_);
},
)
],
));
},
)
I have made an alert dialog where user can update their profile details. In that with image container there is icon button widget. What I want is that when user clicks icon button, pop up menu will display with add/remove image option. Here is my code for alert dialog:
showDialog<void>(
builder: (BuildContext context) {
return AlertDialog(
title: Text('Update details'),
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(8.0))),
content: StatefulBuilder(
builder: (context, setState) { return Container(
width: 400,
child: Form(
key: _formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Stack(
alignment: Alignment.center,
children: [
Container(
width: 100.0,
height: 100.0,
decoration: new BoxDecoration(
shape: BoxShape.circle,
image: new DecorationImage(
fit: BoxFit.cover,
colorFilter: new ColorFilter.mode(Colors.black.withOpacity(0.2), BlendMode.darken),
image: data != null ? MemoryImage(data) : AssetImage("web/icons/contactsDefaultImage.png")
)
)
),
IconButton(icon: Icon(Icons.edit), onPressed: () async {
//display option here
_showPopupMenu();
})
]),
Container(
child: TextFormField(
decoration: InputDecoration(
labelText: 'name'
),
),
),
TextFormField(
decoration: InputDecoration(
labelText: 'email'
),
),
],
),
),
);},
),
actions: <Widget>[
FlatButton(
child: Text('Cancel'),
onPressed: () {
Navigator.of(context).pop();
},
),
FlatButton(child: Text('Save'),
onPressed: () {
// save
},
)
],
);
},
);
I tried to user showMenu for that. But as the position has to be hard-coded I don't was to use it.
what I tried:
void _showPopupMenu() async {
await showMenu(
context: context,
position: RelativeRect.fromLTRB(100, 100, 100, 100),
items: [
PopupMenuItem(
child: Text("add"),
),
PopupMenuItem(
child: Text("remove"),
),
],
elevation: 8.0,
);
}
Now, what i want to know is how can i display it where the icon-button is tapped (without hard-coding the value). And is there another way to do it .i.e without using showMenu.
You can write a method like this and call it on your icon button's onPressed
showPopupMenu(){
showMenu<String>(
context: context,
position: RelativeRect.fromLTRB(25.0, 25.0, 0.0, 0.0), //position where you want to show the menu on screen
items: [
PopupMenuItem<String>(
child: const Text('menu option 1'), value: '1'),
PopupMenuItem<String>(
child: const Text('menu option 2'), value: '2'),
PopupMenuItem<String>(
child: const Text('menu option 3'), value: '3'),
],
elevation: 8.0,
)
.then<void>((String itemSelected) {
if (itemSelected == null) return;
if(itemSelected == "1"){
//code here
}else if(itemSelected == "2"){
//code here
}else{
//code here
}
});
}
Edit: (to show menu at the position where user tapped)
We can have a method like so -
void showPopUpMenuAtTap(BuildContext context, TapDownDetails details) {
showMenu(
context: context,
position: RelativeRect.fromLTRB(
details.globalPosition.dx,
details.globalPosition.dy,
details.globalPosition.dx,
details.globalPosition.dy,
),
// other code as above
);
}
and use it with GestureDetector like so -
GestureDetector(
child: const Icon(Icons.menu),
onTapDown: (details) => showPopUpMenuAtPosition(context, details),
);
Solution if you wish to re-use your button and not a Gesture detector:
Create a key and assign your button the key. Then:
TextButton(
key: _accKey,
text: "Account",
onPressed: () {
final RenderBox renderBox =
_accKey.currentContext?.findRenderObject() as RenderBox;
final Size size = renderBox.size;
final Offset offset = renderBox.localToGlobal(Offset.zero);
showMenu(
context: context,
position: RelativeRect.fromLTRB(
offset.dx,
offset.dy + size.height,
offset.dx + size.width,
offset.dy + size.height),
items: [
PopupMenuItem<String>(
child: const Text('menu option 1'), value: '1'),
PopupMenuItem<String>(
child: const Text('menu option 2'), value: '2'),
PopupMenuItem<String>(
child: const Text('menu option 3'), value: '3'),
]);
}),
what you are looking to is showdialog and alertdialog.
Void<String> testdialog(BuildContext context) {
return showDialog(
barrierDismissible: false,
context: context,
builder: (context) {
return StatefulBuilder(builder: (context, setState) {
return AlertDialog(
title: ....
There are a lot of options you can choose:
You can use:
Banner
Card
Dialog
PopupMenuButton
Or even BottomSheet
I hope it will help