2

昨天问了一个非常相似的问题,关于在 AlertDialog 中显示 GridView 并得到了将 Widget 包装在容器中并添加宽度的完美答案。现在我决定一个 SimpleDialog 会更好,以提供更多的功能/定制,即搜索文本字段和多操作按钮。显示文本字段和图标按钮时,我得到了所需的结果,但是当我尝试添加 GridView 时,它会出错。我应用了之前的规则,但在 UI 消失但没有小部件显示的情况下,我遇到了类似的错误。我试过为不同的小部件添加宽度,但没有成功。这是我的代码...

Future<Null> _neverSatisfied() async {
    return showDialog<Null>(
      context: context,
      barrierDismissible: false, // user must tap button!
      child: new SimpleDialog(
        contentPadding: const EdgeInsets.all(10.0),
        title: new Text(
          'CHOOSE YOUR GIF PROFILE IMAGE',
          style: new TextStyle(fontWeight: FontWeight.bold, color: Colors.blue),
          textAlign: TextAlign.center,
        ),
        children: <Widget>[
          new Column(
            mainAxisSize: MainAxisSize.max,
            children: <Widget>[
              new Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  mainAxisSize: MainAxisSize.min,
                  children: <Widget>[
                    new Padding(padding: new EdgeInsets.all(10.0)),
                    new Expanded(
                        child: new TextField(
                            decoration:
                                new InputDecoration(labelText: "SEARCH GIF'S"),
                            controller: _searchController,
                            onSubmitted: (str) {
                              setState(() {
                                str = _searchController.text;
                              });
                            })),
                    new Padding(padding: new EdgeInsets.all(2.0)),
                    new IconButton(
                      icon: new Icon(
                        Icons.search,
                        color: Colors.blue,
                      ),
                      onPressed: () {
                        print('${_searchController.text}');
                      },
                      highlightColor: Colors.amber,
                      splashColor: Colors.amber,
                      iconSize: 25.0,
                    ),
                  ]),
              new Padding(padding: new EdgeInsets.all(2.0)),

              new Container(
                // Specify some width
                width: MediaQuery.of(context).size.width * .5,
                child: new InkWell(
                  splashColor: Colors.blue,
                  onTap: null,
                  child: new GridView.count(
                      crossAxisCount: 4,
                      childAspectRatio: 1.0,
                      padding: const EdgeInsets.all(4.0),
                      mainAxisSpacing: 4.0,
                      crossAxisSpacing: 4.0,
                      children: <String>[
                        'http://www.for-example.org/img/main/forexamplelogo.png',
                        'http://www.for-example.org/img/main/forexamplelogo.png',
                        'http://www.for-example.org/img/main/forexamplelogo.png',
                        'http://www.for-example.org/img/main/forexamplelogo.png',
                        'http://www.for-example.org/img/main/forexamplelogo.png',
                        'http://www.for-example.org/img/main/forexamplelogo.png',
                        'http://www.for-example.org/img/main/forexamplelogo.png',
                        'http://www.for-example.org/img/main/forexamplelogo.png',
                        'http://www.for-example.org/img/main/forexamplelogo.png',
                        'http://www.for-example.org/img/main/forexamplelogo.png',
                        'http://www.for-example.org/img/main/forexamplelogo.png',
                      ].map((String url) {
                        return new GridTile(
                            child: new Image.network(url, fit: BoxFit.cover, width: 12.0, height: 12.0,));
                      }).toList()),
                )
              ),

              new Padding(padding: new EdgeInsets.all(2.0)),
              new IconButton(
              splashColor: Colors.green,
              icon: new Icon(
                Icons.cancel,
                color: Colors.blue,
              ),
              onPressed: () {
                Navigator.of(context).pop();
              })
            ],
          ),
        ],
      ),
    );
  }

这是我的错误日志...

══╡渲染图书馆捕获的例外╞═════════════════════════════════════════ ════════════════ 在 performLayout() 过程中抛出了以下断言:RenderViewport 不支持返回固有尺寸。计算内在尺寸需要实例化视口的每个子项,这与视口懒惰的观点相悖。如果您只是尝试在主轴方向上收缩包裹视口,请考虑使用 RenderShrinkWrappingViewport 渲染对象(ShrinkWrappingViewport 小部件),它可以在不实现内部维度 API 的情况下实现该效果。

4

1 回答 1

4

该错误本质上意味着有一个滚动区域或一个可以增长的小部件,并且您试图在其中放置另一个滚动区域而没有指定内部滚动区域应该有多大。当 Flutter 尝试计算各种事物的大小时,它不能,因为有两种不同的事物可以增长/收缩;特别是网格的垂直方向是您的问题。如果 gridview 计算了它所有子项的大小,那么它可以根据该大小对所有其余的大小进行排序(如错误消息所述)。但是gridview的整个观点是显示大量数据,这些数据很可能会从屏幕上滚动出来,因此如果要进行该计算,它可能会在使用gridview的正常情况下减慢速度。

我敢打赌 AlertDialog 对高度有限制和/或不滚动,这就是为什么你没有看到它的问题。

要解决您的问题,您有两种选择。如果您将拥有大量项目(如果您描述了您实际尝试制作的内容,它将帮助我回答),请继续使用 gridview,但只需将高度以及它分配给它所在的容器。这样对话框可以很高兴地知道其所有子项的高度,并且网格可以在您给定的高度内调整自己的大小(TBH,我不确定您是否甚至需要再定义宽度)。

另一种选择,如果您没有大量项目(即它们或多或少适合屏幕和/或您不希望它们滚动),请使用包装而不是直接布局的网格你所有的物品。这样做的好处是,当您的方向也发生变化时,它会很好地布置所有内容。

于 2018-03-23T00:10:52.503 回答