Je suis nouveau sur Flutter donc je m'entraîne en créant un formulaire simple. J'ai réalisé en déboguant sur mon iPhone que le clavier virtuel avait déclenché une erreur: "Un RenderFlex a débordé de 29 pixels en bas". J'ai résolu ce problème en enveloppant mon conteneur dans un SingleChildScrollView.

Le problème maintenant est que le contenu de ma colonne n'est plus au centre. Je ne comprends pas pourquoi ...

Voici mon code pour vous aider à comprendre:

List<Widget> _buildBody() {
    var listWidget = List<Widget>();

    SingleChildScrollView singleChild = SingleChildScrollView(
        padding: EdgeInsets.only(top: 1.0),
        child: Container(
          alignment: Alignment.center,
          margin: EdgeInsets.all(30.0),
          padding: EdgeInsets.all(10.0),
          child: Form(
            key: _formKey,
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                Container(
                  margin: EdgeInsets.fromLTRB(0.0, 0.0, 0.0, 50.0),
                  child: Image.asset(
                    'assets/github.png',
                    width: 100.0,
                    height: 100.0,
                  ),
                ),
                Container(
                    margin: EdgeInsets.only(bottom: 10.0),
                    child: TextFormField(
                        controller: _usernameController,
                        autofocus: true,
                        decoration: InputDecoration(
                            hintText: 'Username',
                            suffixIcon: Icon(Icons.account_circle)))),
                Container(
                  child: TextFormField(
                    controller: _passwordController,
                    obscureText: true,
                    decoration: InputDecoration(
                        hintText: 'Password', suffixIcon: Icon(Icons.vpn_key)),
                  ),
                ),
                Container(
                  margin: EdgeInsets.only(top: 10.0),
                  child: RaisedButton(
                    splashColor: Colors.greenAccent,
                    color: Colors.blue,
                    child: Text('Submit'),
                    onPressed: () {
                      _handleSubmit();
                    },
                  ),
                )
              ],
            ),
          ),
        ));

    listWidget.add(singleChild);

    if (_requesting) {
      var modal = new Stack(
        children: [
          new Opacity(
            opacity: 0.3,
            child: const ModalBarrier(dismissible: false, color: Colors.grey),
          ),
          new Center(
            child: new CircularProgressIndicator(),
          ),
        ],
      );
      listWidget.add(modal);
    }

    return listWidget;
  }

  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Github Login'),
        ),
        body: Stack(
          children: _buildBody(),
        ));
  }

J'ai ajouté la propriété "mainAxisAlignment: MainAxisAlignment.center" à ma colonne. Cela a bien fonctionné avant de l'envelopper dans le SingleChildScrollView.

Si quelqu'un pouvait m'aider et m'expliquer pourquoi cela ne fonctionne plus, je l'apprécierais vraiment :)

13
Hurobaki 20 nov. 2018 à 20:33

6 réponses

Meilleure réponse

Solution:

Placez votre widget Stack de niveau supérieur dans Center.

body: Center(child: Stack(
      children: _buildBody(),
    )));

Astuce pour déboguer:

Utilisez Flutter Inspector pour trouver où la mise en page ne va pas.

J'ai édité un peu votre code (pour le faire fonctionner dans mon local) puis j'ai inspecté. Il a montré comme ci-dessous entrez la description de l'image ici Nous avons un Stack et SingleChildScrollView selon le code (reportez-vous au côté droit du diagramme où la pile de widgets est affichée). Comme la taille est déterminée par SingleChildScrollView (contenu à l'intérieur), Stack n'occupe que peu d'espace et par défaut, il est aligné sur top. Alors mettez-le sous Center, la vue Stack entière viendra au centre.

12
Dinesh Balasubramanian 21 nov. 2018 à 04:00

ArtiomLK A suggéré une solution dans les commentaires qui m'a aidé:

Envelopper SingleChildScrollView dans un Center. L'arbre des widgets est:

Center( child: SingleChildScrollView( child: Column(...)))

Aucun des autres n'a aidé.

16
AndrewS 25 juil. 2019 à 13:43

Enveloppez simplement le Column dans un Center. Je l'ai utilisé pour mes applications et il semble centrer le contenu de mon Column même à l'intérieur d'un SingleChildScrollView.

3
Coder 20 nov. 2018 à 18:47

Utilisez le widget LayoutBuilder pour envelopper tout le widget et utilisez le widget Spacer avant et après votre widget centré dans la colonne

    class Home extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('AppBar'),
        ),
        body: LayoutBuilder(builder: (context, constraints) {
          return SingleChildScrollView(
              child: ConstrainedBox(
                  constraints: BoxConstraints(minWidth: constraints.maxWidth, minHeight: constraints.maxHeight),
                  child: IntrinsicHeight(
                    child: Column(
                        mainAxisSize: MainAxisSize.max,
                        children: [
                          Spacer(),
                          Container(
                             child: //your widget
                          ),
                          Spacer()
                        ]
                    ),
                  )
              )
          );
        })
    );
  }
}
0
Amera Abdallah 10 mai 2020 à 04:45

Il existe un autre moyen d'y parvenir:

Center(
    child: ListView(
        shrinkWrap: true,
        children: []
    )

)
1
Matt 1 août 2019 à 08:59

Il y a une section à ce sujet dans la documentation officielle:

Utilisation de SingleChildScrollView avec une colonne

Source: https://api.flutter.dev/flutter/widgets /SingleChildScrollView-class.html

Cependant, j'ai trouvé que l'utilisation d'une combinaison de ce qui précède fonctionnait mieux. À savoir limiter le Column à la taille minimale possible (MainAxisSize.min). Cela devrait être bien, car le SingleChildScrollView prendra autant d'espace que possible à l'écran, avant que le défilement puisse se produire.

Widget _buildPortraitPage() {
    return Center(
      child: SingleChildScrollView(
        child: Column(
          mainAxisSize: MainAxisSize.min, // <-- notice 'min' here. Important
          children: [
            Flexible(
              child: Image.asset('assets/images/my-image.png'),
            ),
            Flexible(
              child: Text('My content'),
            ),
          ],
        ),
      ),
    );
  }

Le moteur de mise en page de Flutter est assez difficile à comprendre.

3
DarkNeuron 7 août 2019 à 12:22