次のコードを使用して、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はコードが多すぎると文句を言うので、ログをコードとしてラップできませんでした)。
==╡LIBRARYのレンダリングによる例外処理CA ================================ ========================= 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位置12:' child.hasSize ':は正しくありません。 I/flutter(4481):別の例外がスローされました:RenderBoxがレイアウトされていません:RenderPhysicalShape#83d92 relayoutBoundary = up2
特定の高さと幅でContainerを使用してみましたが、機能しますが、ListViewをダイアログに収めたいと思います。
SimpleDialogにListViewを含める方法
ただラップListView.builder
は、特定の高さおよび幅を持つ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で呼び出します。
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text('Country List'),
content: getAllSelectedCountry(),
);
}
);
編集済み:
@ Rap'sコメントも使用できます。
これは、将来の訪問者にとってより一般的な回答です。
ListViewでダイアログが必要な場合は、 SimpleDialog を検討する必要があります。 SimpleDialogは、リストにオプションを表示するように設計されています( AlertDialog とは対照的に、ユーザーに何かを通知するためのものです)。
以下に簡単な例を示します。
SimpleDialogの作成プロセスは、ボタンではなくSimpleDialogOptionsと呼ばれるリストアイテムウィジェットを定義することを除いて、基本的にAlertDialogと同じです(どちらもDialogに基づいています)。リストオプションが押されると、応答可能なコールバックが発生します。
// 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;
},
);
ユーザーがアイテムをクリックすると、ダイアログを閉じてアクションを実行できます。
Widget optionOne = SimpleDialogOption(
child: const Text('horse'),
onPressed: () {
Navigator.of(context).pop();
_doSomething();
},
);
上記の例の完全なコードを次に示します。
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;
},
);
}
ListViewをコンテナでラップし、幅をdouble.maxFiniteにすると、ダイアログ内のListViewで問題が発生するiOS/Androidの問題が解決します。
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Container(
width: double.maxFinite,
child: ListView(
children: <Widget>[]
),
),
);
}
);
AlertDialog内にあるColumn内のListViewの場合:
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
content: Container(
width: double.maxFinite,
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Expanded(
ListView(
shrinkWrap: true,
children: <Widget>[]
)
)
]
),
),
);
}
);
以下の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;
最初に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"),
],
),
)
],
);
},
);
私は方法を見つけました...それは少しハッキーですが、より良いオプションがあるかもしれませんが。
このパッケージが必要です:
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
)
),
]
),
);
}
繰り返しますが、私はそれが最高だとは思いませんが、これまでのところ私のために働いています。