Flutter:SimpleDialog中的ListView

时间:2018-04-30 07:23:09

标签: listview flutter

我想在我的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?

11 个答案:

答案 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相反,后者旨在通知用户某些信息)。

这是一个简单的例子:

enter image description here

创建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中将SingleChildScrollViewphysics: 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,
              ),
            )
          ],
        );
      },
    );

输出:

enter image description here