Текстовое поле внутри строки вызывает исключение макета: невозможно вычислить размер

168

Я получаю исключение при рендеринге, которое не понимаю, как исправить. Я пытаюсь создать столбец с 3 строками.

Строка [Изображение]

Строка [TextField]

Ряд [кнопки]

Вот мой код для создания контейнера:

Container buildEnterAppContainer(BuildContext context) {
    var container = new Container(
      padding: const EdgeInsets.all(8.0),
      child: new Column(
        mainAxisAlignment: MainAxisAlignment.start,
        children: <Widget>[
          buildImageRow(context),
          buildAppEntryRow(context),
          buildButtonRow(context)
        ],
      ),
    );
    return container;
  }

и мой код buildAppEntryRow для текстового контейнера

Widget buildAppEntryRow(BuildContext context) {
    return new Row(
      children: <Widget>[
        new TextField(
          decoration: const InputDecoration(helperText: "Enter App ID"),
          style: Theme.of(context).textTheme.body1,
        )
      ],
    );
  }

Когда я бегу, я получаю следующее исключение:

I/flutter ( 7674): BoxConstraints forces an infinite width.
I/flutter ( 7674): These invalid constraints were provided to RenderStack's layout() function by the following
I/flutter ( 7674): function, which probably computed the invalid constraints in question:
I/flutter ( 7674):   RenderConstrainedBox.performLayout (package:flutter/src/rendering/proxy_box.dart:256:13)
I/flutter ( 7674): The offending constraints were:
I/flutter ( 7674):   BoxConstraints(w=Infinity, 0.0<=h<=Infinity)

Если я изменю buildAppEntryRow на TextField вместо этого

 Widget buildAppEntryRow2(BuildContext context) {
    return new TextField(
      decoration: const InputDecoration(helperText: "Enter App ID"),
      style: Theme.of(context).textTheme.body1,
    );
  }

Я больше не получаю исключения. Что мне не хватает в реализации строки, из-за которой она не может рассчитать размер этой строки?

Мэтью Смит
источник
См. Это, чтобы решить проблему выше: stackoverflow.com/a/63698894/10563627
Пареш Мангукия

Ответы:

364

(Я предполагаю, что вы используете a, Rowпотому что TextFieldв будущем хотите разместить другие виджеты рядом с.)

RowВиджет хочет определить характеристическую размер его негибких детей , так что знает , как много места , что он оставил для гибких из них. Однако TextFieldне имеет собственной ширины; он знает только, как изменить размер до полной ширины родительского контейнера. Попробуйте обернуть его в Flexibleили, Expandedчтобы сообщить, Rowчто вы ожидаете, что он TextFieldзаймет оставшееся место:

      new Row(
        children: <Widget>[
          new Flexible(
            child: new TextField(
              decoration: const InputDecoration(helperText: "Enter App ID"),
              style: Theme.of(context).textTheme.body1,
            ),
          ),
        ],
      ),
Коллин Джексон
источник
4
Разве это не должно быть где-нибудь на флаттер-доке?
stt106
1
@ stt106 это -> flutter.io/docs/development/ui/layout/box-constraints Но я согласен, найти его непросто. При этом они не делают решение столь очевидным, как Коллин Джексон выше.
Rap
Использование этого метода приводит mainAxisAlignmentк прерыванию виджета Row. С двумя текстовыми виджетами проблем нет, но с текстовым виджетом и содержащимся в Flexibleнем виджетом Textfield выравнивается по левому краю без интервала.
Hasen
Могу я попросить вас взглянуть на вопрос, связанный с Flutter, здесь: stackoverflow.com/questions/60565658/… ?
Istiaque Ahmed,
По какой-то причине это небольшое изменение потребовало горячего перезапуска Flutter (а не только горячей перезагрузки), чтобы исключение макета исчезло в моем случае.
Magnus W,
38

Вы получаете эту ошибку, потому что TextFieldрасширяется в горизонтальном направлении Row, поэтому нам нужно ограничить ширину TextField, есть много способов сделать это.

  1. Использовать Expanded

     Row(
      children: <Widget>[
        Expanded(child: TextField()),
        OtherWidget(),
      ],
    )
    
  2. Использовать Flexible

    Row(
      children: <Widget>[
        Flexible(child: TextField()),
        OtherWidget(),
      ],
    )
    
  3. Оберните его Containerили SizedBoxи предоставьтеwidth

    Row(
      children: <Widget>[
        SizedBox(width: 100, child: TextField()),
        OtherWidget(),
      ],
    )       
    
CopsOnRoad
источник
2
Эта рекомендация очень полезна. Когда у вас их несколько TextFieldв одном ряду.
CircleOnCircles
11

вы должны использовать гибкий, чтобы использовать текстовое поле внутри строки.

new Row(
              children: <Widget>[
                new Text("hi there"),
                new Container(
                  child:new Flexible(
                        child: new TextField( ),
                            ),//flexible
                ),//container


              ],//widget
            ),//row
Аджит Пол
источник
Я думаю, вам не нужно Container, вы можете использовать Flexibleнапрямую.
Фелипе Августо
6

Решение состоит в том, чтобы поместить вас Text()внутрь одного из следующих виджетов: Либо Expandedили Flexible. Итак, ваш код с использованием Expanded будет выглядеть так:

Expanded(
           child: TextField(
             decoration: InputDecoration(
               hintText: "Demo Text",
               hintStyle: TextStyle(fontWeight: FontWeight.w300, color: Colors.red)
              ),
           ),
        ),
AAEM
источник
5

Как упомянул @Asif Shiraz, у меня была такая же проблема, и я решил ее, обернув столбец в гибкий, вот так,

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
        title: 'Flutter Demo',
        theme: new ThemeData(
          primarySwatch: Colors.blue,
        ),
        home: new Scaffold(
          body: Row(
            children: <Widget>[
              Flexible(
                  child: Column(
                children: <Widget>[
                  Container(
                    child: TextField(),
                  )
                  //container
                ],
              ))
            ],
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
          ),
        ));
  }
}
Шахзад Акрам
источник
0

Простое решение обернуть Text()внутри Container(). Итак, ваш код будет таким:

Container(
      child: TextField()
)

Здесь вы также получаете атрибуты ширины и высоты контейнера, чтобы настроить внешний вид вашего текстового поля. Нет необходимости использовать, Flexibleесли вы обертываете текстовое поле внутри контейнера.

vs_lala
источник
1
не решает вопрос без добавленияwidth: n
user3249027 02
0

У меня такая же проблема.

Если вы хотите, вы можете использовать виджет Table, чтобы избежать подобных проблем с TextField.

Хорхе Вандер Сантана Уренья
источник
0
Row(
      children: [
        Expanded(
          flex: 1,
          child: Padding(
            padding: EdgeInsets.only(left: 5.0,right: 5.0),
            child: TextFormField(
              controller: commentController,
              validator: (String value){
                if(value.isEmpty){
                  // ignore: missing_return
                  return 'Comment cannot be blank.';
                }
              },
              decoration: InputDecoration(
                  labelText: "Comment",
                  labelStyle: TextStyle(
                      fontFamily: 'Montserrat',
                      fontWeight: FontWeight.bold,
                      color: Colors.grey),
                  focusedBorder: UnderlineInputBorder(
                      borderSide: BorderSide(color: Colors.green))),
            ),
          ),
        ),
      ],
    ),
Дилендра Шахи
источник