web-dev-qa-db-ja.com

Flutter:SimpleDialogのListView

次のコードを使用して、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を含める方法

12
Darkhan

ただラップ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コメントも使用できます。

12
Govaadiyo

これは、将来の訪問者にとってより一般的な回答です。

リスト付きのダイアログを作成する方法

ListViewでダイアログが必要な場合は、 SimpleDialog を検討する必要があります。 SimpleDialogは、リストにオプションを表示するように設計されています( AlertDialog とは対照的に、ユーザーに何かを通知するためのものです)。

以下に簡単な例を示します。

enter image description here

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

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>[]
                     )
                  )
               ]
            ),
         ),
      );
   }
);
2
Jose Jet

以下の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;
1
silentsudo

最初に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"),
            ],
          ),
        )
      ],
    );
  },
);
0
Isham Mahajan

私は方法を見つけました...それは少しハッキーですが、より良いオプションがあるかもしれませんが。

このパッケージが必要です:

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

繰り返しますが、私はそれが最高だとは思いませんが、これまでのところ私のために働いています。

0
Jus10