web-dev-qa-db-fra.com

Reconstruction du widget après la sélection de TextField Flutter

Je développe une application Flutter qui devait avoir un formulaire. Ainsi, lorsque l'utilisateur ouvre l'application, un écran de démarrage apparaît avant le formulaire et contient le code suivant:

import 'package:flutter/material.Dart';
import '../model/User.Dart';
import './FileManager.Dart';
import './MyListPage.Dart';

class UserLoader extends StatefulWidget {
  @override
  _UserLoaderState createState() => new _UserLoaderState();
}

class _UserLoaderState extends State<UserLoader> {
  final userFileName = "user_infos.txt";
  User _user;

  @override
  Widget build(BuildContext context) {
    print("build UserLoader");
    final _formKey = new GlobalKey<FormState>();
    final _firstNameController = new TextEditingController();
    final _lastNameController = new TextEditingController();
    final _emailController = new TextEditingController();
    final _phoneController = new TextEditingController();

    return new Scaffold(
        appBar: new AppBar(
          title: new Text("Informations"),
          actions: <Widget>[
            new IconButton(
                icon: const Icon(Icons.save),
                onPressed: () {
                  _user = _onFormValidate(
                      _formKey.currentState,
                      _firstNameController.text,
                      _lastNameController.text,
                      _emailController.text,
                      _phoneController.text);
                })
          ],
        ),
        body: new Center(
          child: new SingleChildScrollView(
              child: new Form(
                  key: _formKey,
                  child: new Column(children: <Widget>[
                    new ListTile(
                      leading: const Icon(Icons.person),
                      title: new TextFormField(
                        decoration: new InputDecoration(
                          hintText: "Prénom",
                        ),
                        keyboardType: TextInputType.text,
                        controller: _firstNameController,
                        validator: _validateName,
                      ),
                    ),
                    new ListTile(
                      leading: const Icon(Icons.person),
                      title: new TextFormField(
                        decoration: new InputDecoration(
                          hintText: "Nom",
                        ),
                        keyboardType: TextInputType.text,
                        controller: _lastNameController,
                        validator: _validateName,
                      ),
                    ),
Etc, etc ...

Cependant, lorsque j'appuie sur TextField, le clavier apparaît et se ferme immédiatement et tout le composant est reconstruit. Il m'est donc impossible de remplir le formulaire ..

Quelqu'un peut-il avoir une solution s'il vous plaît? Merci d'avance !

11
Nadox56

Vous ne nous avez pas donné le code complet pour cela, donc je ne sais pas quel est le contexte.

Un piège dans lequel je suis moi-même tombé (et je peux vous affecter, si je comprends bien votre description) est d'avoir un widget avec état imbriqué dans un autre widget avec état.

Par exemple,

class Parent extends StatefulWidget {
  @override
  ParentState createState() => ParentState();

  (...)
}

class ParentState extends State<Parent> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: Child(),
    );
  }

  (...)
}

class Child extends StatefulWidget {
  @override
  ChildState createState() => ChildState();

  (...)
}

class ChildState extends State<Child> {
  @override
  Widget build(BuildContext context) {
    return TextField(...);
  }

  (...)
}

Le problème ici est qu'une reconstruction de Parent signifie que ParentState().build() est exécutée, et une instance newChild est créée, avec une nouvelle ChildState objet. Ce qui réinitialise tout.

Essayez de ne pas recréer ChildWidget, mais plutôt de l'enregistrer sur ParentState, comme ceci:

class Parent extends StatefulWidget {
  @override
  ParentState createState() => ParentState();

  (...)
}

class ParentState extends State<Parent> {
  Child _child;

  @override
  void initState() {
    _child = Child();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: child,
    );
  }

  (...)
}
// The rest remains the same

Edit: Vous devez juste vous rappeler que, si votre arborescence de widgets est un peu plus complexe, vous devrez peut-être 1) passer un rappel du parent pour notifier les changements d'état, et 2) ne pas oublier d'appeler également setState () sur le Enfant.

12
rbp

il vous suffit de créer une nouvelle classe et de l'importer sur votre classe cible qui a rencontré le problème. par exemple :

Je crée généralement une classe comme celle-ci:

class MiddleWare
{
  static MiddleWare shared = MiddleWare();
  _MiddleWare(){}
  String myText = "my Text";
  // every variables should be here...
}

et

import "MiddleWare.Dart";

class myclass extends StatefulWidget {
  @override
  _myclassState createState() => _myclassState();
}

class _myclassState extends State<myclass> {
  @override
  Widget build(BuildContext context) {
    return Container(child: Text(MiddleWare.shared.myText));
  }
}

c'est tout.

1
Sina.Moradbakhti

essayez de créer une fonction qui reçoit un contexte comme celui-ci

class YourPage extends StatefulWidget {
  const YourPage(Key key) : super(key: key);

  static Future<void> show({ BuildContext context,}) async {
     await Navigator.of(context, rootNavigator: true).Push(
         MaterialPageRoute(
    builder: (context) => YourPage()
    );}

   @override
   _YourPageState createState() => _YourPageState();
}
......YourPage Build.....

puis fournissez le contexte à votre page, lors de la reconstruction, elle aura un contexte de base qui empêche la reconstruction du parent.

onPressed: () async {
             await YourPage.show(context: context);