TextField dentro da linha causa exceção de layout: Não é possível calcular o tamanho

147

Estou recebendo uma exceção de renderização que não entendo como corrigir. Estou tentando criar uma coluna que tem 3 linhas.

Linha [Imagem]

Linha [Campo de texto]

Linha [botões]

Aqui está o meu código para criar o contêiner:

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;
  }

e meu código buildAppEntryRow para o contêiner de texto

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

Quando executo, recebo a seguinte exceção:

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)

Se eu alterar buildAppEntryRow para apenas um TextField, como este

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

Não recebo mais a exceção. O que estou perdendo com a implementação de Linha que está fazendo com que não seja capaz de calcular o tamanho dessa linha?

Matthew Smith
fonte

Respostas:

318

(Presumo que você esteja usando um Rowporque deseja colocar outros widgets ao lado do TextFieldno futuro.)

O Rowwidget deseja determinar o tamanho intrínseco de seus filhos não flexíveis, para saber quanto espaço resta para os filhos flexíveis. No entanto, TextFieldnão tem uma largura intrínseca; ele sabe apenas como se dimensionar para a largura total de seu contêiner pai. Tente envolvê-lo em um Flexibleou Expandeddizer o Rowque você espera TextFieldque ocupe o espaço restante:

      new Row(
        children: <Widget>[
          new Flexible(
            child: new TextField(
              decoration: const InputDecoration(helperText: "Enter App ID"),
              style: Theme.of(context).textTheme.body1,
            ),
          ),
        ],
      ),
Collin Jackson
fonte
3
Isso não deveria estar no documento flutuante em algum lugar?
stt106 11/01/19
1
@ stt106 é -> flutter.io/docs/development/ui/layout/box-constraints Mas eu concordo, não é fácil de encontrar. Eles também não tornam a solução tão óbvia quanto Collin Jackson fez acima.
rap Rap
O uso deste método é interrompido mainAxisAlignmentpara o widget Linha. Com dois widgets de texto, não há problema, mas com um widget de texto e um widget de campo de texto contido Flexiblenele é alinhado à esquerda sem espaçamento.
Hasen
Posso pedir para você dar uma olhada em uma pergunta relacionada ao Flutter aqui: stackoverflow.com/questions/60565658/… ?
Istiaque Ahmed 6/03
30

Você recebe esse erro porque se TextFieldexpande na direção horizontal e o mesmo acontece com o Row, portanto, precisamos restringir a largura do TextField, existem muitas maneiras de fazê-lo.

  1. Usar Expanded

     Row(
      children: <Widget>[
        Expanded(child: TextField()),
        OtherWidget(),
      ],
    )
  2. Usar Flexible

    Row(
      children: <Widget>[
        Flexible(child: TextField()),
        OtherWidget(),
      ],
    )
  3. Embrulhe Containerou SizedBoxforneçawidth

    Row(
      children: <Widget>[
        SizedBox(width: 100, child: TextField()),
        OtherWidget(),
      ],
    )       
CopsOnRoad
fonte
2
Esta recomendação é muito útil. Quando você tem vários TextFieldem uma linha.
Ben
11

você deve usar o Flexible para usar um campo de texto dentro de uma linha.

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


              ],//widget
            ),//row
Ajit Paul
fonte
Eu acho que você não precisa do Container, você pode usar o Flexiblediretamente.
Felipe Augusto
6

A solução é envolver o seu Text()um dentro dos seguintes widgets: De qualquer Expandedou Flexible. Portanto, seu código usando o Expanded será como:

Expanded(
           child: TextField(
             decoration: InputDecoration(
               hintText: "Demo Text",
               hintStyle: TextStyle(fontWeight: FontWeight.w300, color: Colors.red)
              ),
           ),
        ),
AAEM
fonte
5

Como @Asif Shiraz mencionou, eu tinha o mesmo problema e resolvi isso envolvendo a Wrapping Column em um Flexible, aqui assim:

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,
          ),
        ));
  }
}
Shahzad Akram
fonte
0

Uma solução simples é envolver seu Text()interior a Container(). Portanto, seu código será como:

Container(
      child: TextField()
)

Aqui você também obtém o atributo de largura e altura de um contêiner para ajustar a aparência do seu campo de texto. Não é necessário usar Flexiblese você estiver agrupando seu campo de texto dentro de um Contêiner.

vs_lala
fonte
1
não resolve a questão sem adicionar #width: n
user3249027 2/19/19