TextField à l'intérieur de Row provoque une exception de mise en page: impossible de calculer la taille

147

J'obtiens une exception de rendu que je ne comprends pas comment corriger. J'essaye de créer une colonne qui a 3 lignes.

Ligne [Image]

Ligne [TextField]

Ligne [Buttons]

Voici mon code pour construire le conteneur:

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

et mon code buildAppEntryRow pour le conteneur de texte

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

Quand je cours, j'obtiens l'exception suivante:

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)

Si je change buildAppEntryRow en juste un TextField comme ceci

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

Je n'ai plus l'exception. Que me manque-t-il avec l'implémentation de la ligne qui l'empêche de calculer la taille de cette ligne?

Matthew Smith
la source

Réponses:

318

(Je suppose que vous utilisez un Rowparce que vous souhaitez mettre d'autres widgets à côté du TextFielddans le futur.)

Le Rowwidget veut déterminer la taille intrinsèque de ses enfants non flexibles afin de savoir combien d'espace il lui reste pour les enfants flexibles. Cependant, TextFieldn'a pas de largeur intrinsèque; il ne sait comment se dimensionner que sur toute la largeur de son conteneur parent. Essayez de l'envelopper dans un Flexibleou Expandedpour dire au Rowque vous vous attendez TextFieldà ce que le occupe l'espace restant:

      new Row(
        children: <Widget>[
          new Flexible(
            child: new TextField(
              decoration: const InputDecoration(helperText: "Enter App ID"),
              style: Theme.of(context).textTheme.body1,
            ),
          ),
        ],
      ),
Collin Jackson
la source
3
Cela ne devrait-il pas être sur Flutter doc quelque part?
stt106
1
@ stt106 c'est -> flutter.io/docs/development/ui/layout/box-constraints Mais je suis d'accord, ce n'est pas facile à trouver. Ils ne rendent pas non plus la solution aussi évidente que Collin Jackson l'a fait ci-dessus.
Rap
L'utilisation de cette méthode interrompt mainAxisAlignmentle widget Row. Avec deux widgets de texte, il n'y a pas de problème, mais avec un widget de texte et un widget Textfield qu'il contient, Flexibleil est aligné à gauche sans espacement.
Hasen le
Puis-je vous demander de jeter un coup d'œil à une question liée à Flutter ici: stackoverflow.com/questions/60565658/... ?
Istiaque Ahmed
30

Vous obtenez cette erreur parce que se TextFielddéveloppe dans le sens horizontal, tout comme le Row, nous devons donc limiter la largeur du TextField, il existe de nombreuses façons de le faire.

  1. Utilisation Expanded

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

    Row(
      children: <Widget>[
        Flexible(child: TextField()),
        OtherWidget(),
      ],
    )
  3. Enveloppez-le dans Containerou SizedBoxet fournissezwidth

    Row(
      children: <Widget>[
        SizedBox(width: 100, child: TextField()),
        OtherWidget(),
      ],
    )       
CopsOnRoad
la source
2
Cette recommandation est si utile. Lorsque vous en avez plusieurs TextFieldà la suite.
Ben le
11

vous devez utiliser Flexible pour utiliser un champ de texte à l'intérieur d'une ligne.

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


              ],//widget
            ),//row
Ajit Paul
la source
Je pense que vous n'avez pas besoin du Container, vous pouvez utiliser le Flexibledirectement.
Felipe Augusto
6

La solution consiste à envelopper votre Text()intérieur dans l'un des widgets suivants: Soit Expandedou Flexible. Ainsi, votre code utilisant Expanded sera comme:

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

Comme @Asif Shiraz l'a mentionné, j'ai eu le même problème et je l'ai résolu en enveloppant la colonne dans un flexible, ici comme ça,

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
la source
0

Une solution simple consiste à envelopper votre Text()intérieur a Container(). Donc, votre code sera comme:

Container(
      child: TextField()
)

Ici, vous obtenez également l'attribut width et height d'un conteneur pour ajuster l'apparence de votre champ de texte. Pas besoin d'utiliser Flexiblesi vous encapsulez votre champ de texte à l'intérieur d'un conteneur.

vs_lala
la source
1
ne résout pas la question sans ajouterwidth: n
user3249027