I want to show a SimpleDialog with ListView.builder in my Flutter app with this code:
showDialog(
context: context,
builder: (BuildContext context) {
SImply in the content
we need to use a Container
with fixed height and width.
and the use ListView
as a child of Container
.
scrollDialogFunction(){
return showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('List of Index'),
content: Container(
width: 350.0,
height: 250,// Change as per your requirement
child: ListView.builder(
itemCount: 150,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(index.toString()),
);
},
),
),
actions: [Padding(
padding: const EdgeInsets.all(8.0),
child: Text("ok",style: TextStyle(fontSize: 18),),
)],
);
});
}
Just wrap ListView.builder
in a Container
with a specific height and width.
Widget setupAlertDialoadContainer() {
return Container(
height: 300.0, // Change as per your requirement
width: 300.0, // Change as per your requirement
child: ListView.builder(
shrinkWrap: true,
itemCount: 5,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text('Gujarat, India'),
);
},
),
);
}
And call the above method in showDialog.
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Country List'),
content: setupAlertDialoadContainer(),
);
});
EDITED:
You can go with @Rap's comment too.
I found a way... Although it's a bit hacky, and so there may be a better option.
You'll need this package:
import 'package:flutter/services.dart';
Create the widget:
class MyDialog extends StatefulWidget {
MyDialog ({Key key}) : super(key: key);
MyDialogState createState() => new MyDialogState();
}
class MyDialogState extends State<MyDialog> {
If the screen rotates it screws things up because the dialog maintains it's original size. You can probably fix that with a bit of effort, but I just lock it to prevent rotating, like this:
@override
initState() { super.initState();
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
}
Then I unlock it like this at the end:
@override
dispose() { super.dispose();
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeRight,
DeviceOrientation.landscapeLeft,
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
}
So that stops the dialog from screwing up. Then I get the size and width of the screen in the build method:
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
Then followed with this layout:
return ConstrainedBox(
constraints: BoxConstraints(maxHeight: height, maxWidth: width),
child: Column(
children: <Widget>[
Expanded(
child: GridView.count(
primary: false,
padding: const EdgeInsets.all(20.0),
crossAxisSpacing: 10.0,
crossAxisCount: 3,
children: _images
)
),
]
),
);
}
..again, I don't think it's the best, but it's been working for me so far.
showDialog(context: parentcontext,
builder: (context){
return SimpleDialog(
title: Text('create post'),
children: <Widget>[
SimpleDialogOption(
onPressed: handleImageTaking,
child: Text('take a pic'),
),
SimpleDialogOption(
onPressed: handleImageSelecting,
child: Text('select a pic'),
),
SimpleDialogOption(
child: Text('cancel'),
onPressed: (){
Navigator.pop(context);
},
)
],
);
});
This is a more general answer for future visitors.
If you want a dialog with a ListView, you should consider a SimpleDialog. A SimpleDialog is designed to show options in a list (as opposed to an AlertDialog, which is meant to notify the user of something).
Here is a simple example:
The process of creating a SimpleDialog is basically the same as for an AlertDialog (they are both based on Dialog), except that you define list item widgets called SimpleDialogOptions instead of buttons. When a list option is pressed a callback is fired that you can respond to.
// set up the list options
Widget optionOne = SimpleDialogOption(
child: const Text('horse'),
onPressed: () {},
);
Widget optionTwo = SimpleDialogOption(
child: const Text('cow'),
onPressed: () {},
);
Widget optionThree = SimpleDialogOption(
child: const Text('camel'),
onPressed: () {},
);
Widget optionFour = SimpleDialogOption(
child: const Text('sheep'),
onPressed: () {},
);
Widget optionFive = SimpleDialogOption(
child: const Text('goat'),
onPressed: () {},
);
// set up the SimpleDialog
SimpleDialog dialog = SimpleDialog(
title: const Text('Choose an animal'),
children: <Widget>[
optionOne,
optionTwo,
optionThree,
optionFour,
optionFive,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return dialog;
},
);
When a user clicks an item you can close the dialog an perform some action.
Widget optionOne = SimpleDialogOption(
child: const Text('horse'),
onPressed: () {
Navigator.of(context).pop();
_doSomething();
},
);
Here is the full code for the example above.
main.dart
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'SimpleDialog',
home: Scaffold(
appBar: AppBar(
title: Text('SimpleDialog'),
),
body: MyLayout()),
);
}
}
class MyLayout extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: RaisedButton(
child: Text('Show alert'),
onPressed: () {
showAlertDialog(context);
},
),
);
}
}
// replace this function with the examples above
showAlertDialog(BuildContext context) {
// set up the list options
Widget optionOne = SimpleDialogOption(
child: const Text('horse'),
onPressed: () {
print('horse');
Navigator.of(context).pop();
},
);
Widget optionTwo = SimpleDialogOption(
child: const Text('cow'),
onPressed: () {
print('cow');
Navigator.of(context).pop();
},
);
Widget optionThree = SimpleDialogOption(
child: const Text('camel'),
onPressed: () {
print('camel');
Navigator.of(context).pop();
},
);
Widget optionFour = SimpleDialogOption(
child: const Text('sheep'),
onPressed: () {
print('sheep');
Navigator.of(context).pop();
},
);
Widget optionFive = SimpleDialogOption(
child: const Text('goat'),
onPressed: () {
print('goat');
Navigator.of(context).pop();
},
);
// set up the SimpleDialog
SimpleDialog dialog = SimpleDialog(
title: const Text('Choose an animal'),
children: <Widget>[
optionOne,
optionTwo,
optionThree,
optionFour,
optionFive,
],
);
// show the dialog
showDialog(
context: context,
builder: (BuildContext context) {
return dialog;
},
);
}
Used SingleChildScrollView
with physics: NeverScrollableScrollPhysics()
and shrinkWrap: true
in your ListView
showDialog(
context: context,
builder: (_) {
return AlertDialog(
title: widget,
content: SingleChildScrollView( //MUST TO ADDED
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
...//any widgets,
ListView.builder(
shrinkWrap: true, //MUST TO ADDED
physics: NeverScrollableScrollPhysics(), //MUST TO ADDED
itemCount: model.length,
itemBuilder: (BuildContext c, int index) {
return ListTile();
})
],
),
),
);
},
);