Флаттер - Как отобразить GridView в поле SimpleDialog?

Вчера задал очень похожий вопрос, касающийся отображения GridView в AlertDialog, и получил идеальный ответ для упаковки Widget в контейнер и добавления ширины. Теперь я решил, что SimpleDialog будет лучше для обеспечения большей функциональности / настройки, то есть поиска текстовых полей и кнопки с несколькими действиями. Я получаю желаемые результаты при отображении текстового поля и IconButton, но при попытке добавить GridView выдает ошибку. Я применил предыдущие правила, но я получаю похожие ошибки, когда пользовательский интерфейс исчезает, но виджет не отображается. Я попытался добавить ширину для разных виджетов без удачи. Вот мой код...

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

Вот мой журнал ошибок...

══╡ ИСКЛЮЧЕНИЕ ПРИОБРЕТЕНО ОТНОСИТЕЛЬНОЙ БИБЛИОТЕКОЙ ╞════════════════════════════════════════════════════════ Во время выполнения executeLayout() было выдвинуто следующее утверждение: RenderViewport не поддерживает возврат внутренних измерений. Вычисление внутренних измерений потребовало бы создания экземпляров каждого дочернего элемента окна просмотра, что побеждает ленивость точки просмотра. Если вы просто пытаетесь сжать область просмотра в направлении главной оси, рассмотрите объект визуализации RenderShrinkWrappingViewport (виджет ShrinkWrappingViewport), который достигает этого эффекта без реализации встроенного API измерения.

1 ответ

Решение

Эта ошибка по сути означает, что существует область прокрутки или виджет, который может расти, и вы пытаетесь поместить в него другую область прокрутки, не указывая, насколько большой должна быть внутренняя область прокрутки. Когда флаттер пытается вычислить размер различных вещей, он не может этого сделать, потому что есть две разные вещи, которые могут увеличиваться / уменьшаться; в частности, вертикальное направление сетки является проблемой в вашем случае. Если gridview рассчитывает размер всех своих дочерних элементов, он может затем отсортировать все остальные размеры в соответствии с этим (как говорится в сообщении об ошибке). Но вся суть gridview заключается в том, чтобы отображать большой объем данных, который, скорее всего, прокручивается за пределы экрана, и поэтому, если бы он делал это вычисление, это могло бы замедлить процесс в обычном случае использования gridview.

Могу поспорить, что AlertDialog имеет ограничение по высоте и / или не прокручивает, и поэтому вы не видели проблемы для него.

Чтобы решить вашу проблему, у вас есть два варианта. Если у вас будет большое количество предметов (это помогло бы мне ответить, если бы вы описали, что вы на самом деле пытались сделать), продолжайте использовать gridview, но просто назначьте высоту и для контейнера, в котором он находится. Таким образом диалоговое окно может масштабироваться счастливо, зная высоту всех его дочерних элементов, и сетка может измерять себя в пределах высоты, которую вы задали (TBH Я не уверен, что вам даже нужно больше определять ширину).

Другой вариант, если у вас нет большого количества элементов (т.е. они будут более или менее помещаться на экране и / или вы не хотите, чтобы они прокручивались), используйте обертку вместо сетки, которая будет непосредственно размещаться все ваши предметы. Преимущество в том, что все будет хорошо выкладываться, когда меняется и ваша ориентация.

Другие вопросы по тегам