How to move slider scroll in the AlertDialog in Flutter? - flutter

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'),
),
],
);
});
});
}

Related

How to reduce the height of AlertDialog which includes a slider?

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'),
),
],
),
);

flutter/dart: how to control the column size?

I need to display a set of options on a pop-up.
The issue that I am having is that the column is taking up all the space.
is there a way around this or another widget I should be using?
I tried using list view but it nothing ends up showing up
_displayJobTypeAlert(BuildContext context) {
return showDialog(
builder: (context) {
return AlertDialog(
title: Text('What type of job is this?'),
content: Column(
//shrinkWrap: true,
// ignore: prefer_const_literals_to_create_immutables
children: [
TextButton(
onPressed: () {
_updateJobField(_jobType, jobTypeColumn, 'Handyman');
},
child: const Text('Handyman'),
),
TextButton(
onPressed: () {
_updateJobField(_jobType, jobTypeColumn, 'Landscaping');
},
child: const Text('Landscaping'),
),
TextButton(
onPressed: () {
_updateJobField(_jobType, jobTypeColumn, 'Plumming');
},
child: const Text('Plumming'),
),
TextButton(
onPressed: () {
_updateJobField(_jobType, jobTypeColumn, 'Remodeling');
},
child: const Text('Remodeling'),
),
TextButton(
onPressed: () {
_updateJobField(_jobType, jobTypeColumn, 'Roofing');
},
child: const Text('Roofing'),
),
TextButton(
onPressed: () {
_updateJobField(_jobType, jobTypeColumn, 'Electrical');
},
child: const Text('Electrical'),
),
],
),
);
},
context: context,
);
}
Instruct the Column widget to take the minimum size it requires:
Column(
mainAxisSize: MainAxisSize.min,
children: [...]
)
I took out column
I used actions instead of children and it worked!
Future _displayJobTypeAlert(BuildContext context) {
return showDialog(
builder: (context) {
return AlertDialog(
elevation: 24.0,
title: Text('What type of job is this?'),
actions:
//Column(
//shrinkWrap: true,
// ignore: prefer_const_literals_to_create_immutables
//children:
[
TextButton(
onPressed: () {
_updateJobField(_jobType, jobTypeColumn, 'Handyman');
Navigator.pop(context);
},
child: const Text('Handyman'),
),
TextButton(
onPressed: () {
_updateJobField(_jobType, jobTypeColumn, 'Landscaping');
Navigator.pop(context);
},
child: const Text('Landscaping'),
),
TextButton(
onPressed: () {
_updateJobField(_jobType, jobTypeColumn, 'Plumming');
Navigator.pop(context);
},
child: const Text('Plumming'),
),
TextButton(
onPressed: () {
_updateJobField(_jobType, jobTypeColumn, 'Remodeling');
Navigator.pop(context);
},
child: const Text('Remodeling'),
),
TextButton(
onPressed: () {
_updateJobField(_jobType, jobTypeColumn, 'Roofing');
Navigator.pop(context);
},
child: const Text('Roofing'),
),
TextButton(
onPressed: () {
_updateJobField(_jobType, jobTypeColumn, 'Electrical');
Navigator.pop(context);
},
child: const Text('Electrical'),
),
],
//),
);
},
context: context,
);
}

Using provider within alert dialog does not work

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),
));
},
),
),

How to deal with setState properly

void showSimpleCustomDialog(BuildContext context, String listName) async{
if(randList.isEmpty){
randList = await theDb.queryWhere("$listName");
}else{
randList.clear();
randList = await theDb.queryWhere("$listName");
}
setState((){
});
String randValue = "Click generate new to get a random value";
Dialog simpleDialog = Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
child: Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
child: Text(
"$randValue"
),
),
Padding(
child: Row(
children: <Widget>[
RaisedButton(
color: Colors.blue,
onPressed: ()
String lol = randList[0 + rng.nextInt(randList.length - 0)].getItem();
print(randValue);
setState(() {
randValue = lol;
});
},
child: Text(
'generate new',
style: TextStyle(fontSize: 18.0, color: Colors.white),
),
)
],
),
),
],
),
),
);
showDialog(
context: context, builder: (BuildContext context) => simpleDialog);}
When I am clicking on "generate new" button I want to update my randomValue and to display that randomValue as Text Widget. To do that dynamically Im using setState, but it is not working, and i dont understand why. Please help me.
You should use StatefulBuilder with dialogue.
showDialog(
context: context,
builder: (context) {
String contentText = "Content of Dialog";
return StatefulBuilder(
builder: (context, setState) {
return AlertDialog(
title: Text("Title of Dialog"),
content: Text(contentText),
actions: <Widget>[
FlatButton(
onPressed: () => Navigator.pop(context),
child: Text("Cancel"),
),
FlatButton(
onPressed: () {
setState(() {
contentText = "Changed Content of Dialog";
});
},
child: Text("Change"),
),
],
);
},
);
},

Display pop up menu when icon button widget is clicked Flutter

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