我需要从rest webservice动态加载列表城市,让用户从警报对话框中选择一个城市。我的代码:
createDialog() {
fetchCities().then((response) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Wybierz miasto'),
content: Container(
height: 200.0,
width: 400.0,
child: ListView.builder(
shrinkWrap: true,
itemCount: response.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(response[index].name),
onTap: () => citySelected(response[index].id),
);
},
),
),
);
}
);
});
}
结果 - 对话框始终为200x400,即使只有2个城市可用,底部还有不必要的空间:
如何使对话框的宽度/高度适合实际的项目大小?如果我省略height
和width
参数,我得到异常并且没有显示对话框。在原生Android Java中,我永远不需要指定任何维度,因为对话框自动调整大小以适应。
如何修复我的代码以正确调整对话框的大小?请注意,我不知道项目计数,它是动态的。
[编辑]
按照建议,我用列包装内容:
createDialog() {
fetchCities().then((response) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Wybierz miasto'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
child: ListView.builder(
shrinkWrap: true,
itemCount: response.length,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text(response[index].name),
onTap: () => citySelected(response[index].id),
);
},
),
)
]
),
);
}
);
});
}
结果 - 例外:
I / flutter(5917):══╡通过渲染图书馆的例外情况╞══════════════════════════════════════════════════════════════════════════════════════════════════ ═/ / /(5917):在performLayout()期间抛出以下断言:I / flutter(5917):RenderViewport没有支持返回内在维度。 I / flutter(5917):计算内在维度需要实例化视口的每个子节点,这样我/ flutter(5917):使视口点变得懒惰。
更通用的代码来测试:
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Select city'),
content: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
child: ListView.builder(
shrinkWrap: true,
itemCount: 2,
itemBuilder: (BuildContext context, int index) {
return ListTile(
title: Text("City"),
onTap: () => {},
);
},
),
)
]
),
);
}
);
将你的qazxsw poi包装在qazxsw poi中,在content参数内,在其中设置Container
,在Column属性中
你能尝试一下吗? 它至少对我有用。如果你需要一个例子告诉我。
Column
UPDATE
您只需在按钮或按下某些内容后显示此AreaPicker。
mainAxisSize.min
我知道现在已经很晚了,但你试过这个吗?
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
class SmartDialog extends StatelessWidget {
const SmartDialog({
Key key,
this.title,
this.titlePadding,
this.content,
this.contentPadding = const EdgeInsets.fromLTRB(24.0, 20.0, 24.0, 24.0),
this.actions,
this.semanticLabel,
}) : assert(contentPadding != null),
super(key: key);
final Widget title;
final EdgeInsetsGeometry titlePadding;
final Widget content;
final EdgeInsetsGeometry contentPadding;
final List<Widget> actions;
final String semanticLabel;
@override
Widget build(BuildContext context) {
final List<Widget> children = <Widget>[];
String label = semanticLabel;
if (title != null) {
children.add(new Padding(
padding: titlePadding ?? new EdgeInsets.fromLTRB(24.0, 24.0, 24.0, content == null ? 20.0 : 0.0),
child: new DefaultTextStyle(
style: Theme.of(context).textTheme.title,
child: new Semantics(child: title, namesRoute: true),
),
));
} else {
switch (defaultTargetPlatform) {
case TargetPlatform.iOS:
label = semanticLabel;
break;
case TargetPlatform.android:
case TargetPlatform.fuchsia:
label = semanticLabel ?? MaterialLocalizations.of(context)?.alertDialogLabel;
}
}
if (content != null) {
children.add(new Flexible(
child: new Padding(
padding: contentPadding,
child: new DefaultTextStyle(
style: Theme.of(context).textTheme.subhead,
child: content,
),
),
));
}
if (actions != null) {
children.add(new ButtonTheme.bar(
child: new ButtonBar(
children: actions,
),
));
}
Widget dialogChild = new Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: children,
);
if (label != null)
dialogChild = new Semantics(
namesRoute: true,
label: label,
child: dialogChild
);
return new Dialog(child: dialogChild);
}
}
这是我的最终解决方案:
class AreaPicker extends StatelessWidget {
final List<Area> items;
AreaPicker(this.items);
@override
Widget build(BuildContext context) {
return SmartDialog(
title: Text('Select Area'),
actions: <Widget>[
FlatButton(
textColor: Colors.black,
child: Text('Rather not say'),
onPressed: () {
Navigator.of(context, rootNavigator: true).pop();
},
)
],
content: Container(
height: MediaQuery.of(context).size.height / 4,
child: ListView.builder(
shrinkWrap: true,
itemExtent: 70.0,
itemCount: areas.length,
itemBuilder: (BuildContext context, int index) {
final Area area = areas[index];
return GestureDetector(
child: Center(
child: Text(area.name),
),
onTap: () {
Navigator.of(context, rootNavigator: true).pop();
// some callback here.
}
);
},
),
)
);
}
}
它基于Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
child: ListView.builder(
shrinkWrap: true,
...
).build(context),
);
],
);
,到目前为止它工作正常。我正在分享它,因为它可能有用,问题并非无足轻重。