我想在我的Flutter应用程序中使用以下代码显示带有ListView.builder的SimpleDialog:
showDialog(
context: context,
builder: (BuildContext context) {
return new SimpleDialog(
children: <Widget>[
new FittedBox(
child: new ListView(
children: <Widget>[
new Text("one"),
new Text("two"),
],
),
)
],
);
},
);
给出了这个错误(抱歉,我无法将日志包装为代码,因为Stackoverflow抱怨代码太多了):
= =╡通过渲染图书馆的例外情况╞═══════════════════════════════════════════════════════════════════════════════════════════════ ══════════════════════ I / flutter(4481):在performLayout()期间抛出以下断言: I / flutter(4481):RenderViewport不支持返回内部维度。 I / flutter(4481):计算内在维度需要实例化视口的每个子节点 I / flutter(4481):击败了懒惰的视点。 I / flutter(4481):如果您只是想在主轴方向上收缩包装视口,请考虑 I / flutter(4481):RenderShrinkWrappingViewport渲染对象(ShrinkWrappingViewport小部件),实现了 I / flutter(4481):没有实现内在维度API的效果。 I / flutter(4481): ... I / flutter(4481):抛出了另一个异常:RenderBox没有布局:RenderPhysicalShape#83d92 relayoutBoundary = up2 NEEDS-PAINT I / flutter(4481):抛出另一个异常:'package:flutter / src / rendering / shifted_box.dart':断言失败:第310行pos 12:'child.hasSize':不是真的。 I / flutter(4481):抛出另一个异常:RenderBox未布局:RenderPhysicalShape#83d92 relayoutBoundary = up2
我尝试使用具有特定高度和宽度的Container,并且它可以工作,但我希望ListView能够适应对话框。
如何在SimpleDialog中包含ListView?
答案 0 :(得分:8)
只需将Container
包装在具有特定高度和宽度的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'),
);
},
),
);
}
中。
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Country List'),
content: getAllSelectedCountry(),
);
}
);
并在 showDialog 中调用上述方法。
header('Content-Type: image/png');
imagepng($im);
已编辑:
您也可以添加 @Rap的 评论。
答案 1 :(得分:3)
这是对将来的访问者的更一般的答案。
如果要使用ListView进行对话框,则应考虑使用SimpleDialog。 SimpleDialog旨在显示列表中的选项(与AlertDialog相反,后者旨在通知用户某些信息)。
这是一个简单的例子:
创建SimpleDialog的过程与AlertDialog基本上相同(它们都基于Dialog),除了您定义名为SimpleDialogOptions而不是按钮的列表项小部件。按下列表选项后,将触发您可以响应的回调。
script(caesar('encrypt' text), caesar('decrypt', text, key))
当用户单击某个项目时,您可以关闭对话框并执行一些操作。
// 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;
},
);
这是上面示例的完整代码。
main.dart
Widget optionOne = SimpleDialogOption(
child: const Text('horse'),
onPressed: () {
Navigator.of(context).pop();
_doSomething();
},
);
答案 2 :(得分:3)
将 width: double.maxFinite
添加到 container
解决了我的问题。
@override
Widget build(BuildContext context) {
return AlertDialog(
title: Text('Sample Dialog'),
content: Container(
width: double.maxFinite,
child: ListView(
children: <Widget>[
Text('Item 1'),
Text('Item 2'),
],
),
),
);
}
答案 3 :(得分:1)
您可以在下面为SimpleDialogOptions代码创建单独的方法方法:
final SimpleDialog dialog = new SimpleDialog(
title: const Text('Select assignment'),
children: <Widget>[
new SimpleDialogOption(
onPressed: () { Navigator.pop(context); },
child: const Text('Text one'),
),
new SimpleDialogOption(
onPressed: () {},
child: const Text('Text two'),
),
],
);
return dialog;
答案 4 :(得分:1)
在您的ListView中将SingleChildScrollView
和physics: NeverScrollableScrollPhysics()
和shrinkWrap: true
一起使用
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();
})
],
),
),
);
},
);
答案 5 :(得分:0)
我找到了一种方法......虽然它有点hacky,所以可能有更好的选择。
你需要这个包裹:
import 'package:flutter/services.dart';
创建小部件:
class MyDialog extends StatefulWidget {
MyDialog ({Key key}) : super(key: key);
MyDialogState createState() => new MyDialogState();
}
class MyDialogState extends State<MyDialog> {
如果屏幕旋转,它会搞砸,因为对话框保持原始大小。您可以通过一些努力来解决这个问题,但我只是将其锁定以防止旋转,如下所示:
@override
initState() { super.initState();
SystemChrome.setPreferredOrientations([
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
}
然后我在最后解锁它:
@override
dispose() { super.dispose();
SystemChrome.setPreferredOrientations([
DeviceOrientation.landscapeRight,
DeviceOrientation.landscapeLeft,
DeviceOrientation.portraitUp,
DeviceOrientation.portraitDown,
]);
}
这样就可以阻止对话框搞砸了。然后我在构建方法中获得屏幕的大小和宽度:
@override
Widget build(BuildContext context) {
double width = MediaQuery.of(context).size.width;
double height = MediaQuery.of(context).size.height;
然后是这个布局:
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
)
),
]
),
);
}
再次,我认为这不是最好的,但到目前为止它一直在为我工作。
答案 6 :(得分:0)
将ListView包裹在容器中并为其设置宽度:double.maxFinite,可解决iOS / Android在对话框中无法使用ListView的问题:
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
child: Container(
width: double.maxFinite,
child: ListView(
children: <Widget>[]
),
),
);
}
);
答案 7 :(得分:0)
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);
},
)
],
);
});
答案 8 :(得分:0)
在content
中,我们需要使用固定高度和宽度的Container
。
并将ListView
用作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),),
)],
);
});
}
答案 9 :(得分:-1)
首先使用itemExtent属性对其进行了尝试,但这不起作用。 如果您的商品是静态的,只需将ListView包装在具有定义的高度和宽度的容器中即可。
showDialog(
context: context,
builder: (BuildContext context) {
return new SimpleDialog(
children: <Widget>[
new Container(
height: 100.0,
width: 100.0,
child: new ListView(
children: <Widget>[
new Text("one"),
new Text("two"),
],
),
)
],
);
},
);
答案 10 :(得分:-1)
使用 spread operator (...)
迭代 List 或者如果 List 可以为 null 则使用 null-aware spread operator (...?)
List<String> values = ['one', 'two', 'three'];
await showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
title: Text("Select Value"),
children: [
...values.map((value) {
return SimpleDialogOption(child: Text(value));
}),
],
);
},
);
使用列表视图:
List<String> values = ['one', 'two', 'three'];
await showDialog(
context: context,
builder: (BuildContext context) {
return SimpleDialog(
title: Text("Select Value"),
children: [
SizedBox(
width: MediaQuery.of(context).size.width,
child: ListView.builder(
shrinkWrap: true,
itemBuilder: (ctx, index) {
return SimpleDialogOption(
onPressed: () => Navigator.pop(context),
child: Center(
child: Text(values[index]),
),
);
},
itemCount: values.length,
),
)
],
);
},
);
输出: