Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Widget rebuild after TextField selection Flutter

I'm developping a Flutter App that needed to have a form. So when the user open the app, a Splash Screen appear before the form that have the following code :

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 ...

However when i tap the TextField, the keyboard appear and close immediately and all the component is rebuild. So it is impossible for me to complete the form..

Can someone have a solution please? Thanks in advance !

like image 532
Nadox56 Avatar asked May 11 '18 15:05

Nadox56


People also ask

How do you force a Flutter widget to rebuild?

The solution is to pass a new Key to WidgetB every time we need it to be rebuilt: WidgetA will see that WidgetB has changed and will rebuild it when setState is called. In other words, whenever a stateful widget's Key property changes, calling setState on its parent will force a rebuild of the stateful widget.

How do I stop rebuild widget in Flutter?

When the instance of a widget stays the same; Flutter purposefully won't rebuild children. It implies that you can cache parts of your widget tree to prevent unnecessary rebuilds. Thanks to that const keyword, the instance of DecoratedBox will stay the same even if build were called hundreds of times.

How build () method works how it rebuild itself Flutter?

The build method is called any time you call setState , your widget's dependencies update, or any of the parent widgets are rebuilt (when setState is called inside of those). Your widget will depend on any InheritedWidget you use, e.g. Theme. of(context) , MediaQuery. of(context) etc.


3 Answers

You haven't given us the entire code for this, so I don't know what the context is.

One pitfall I myself have fallen into (and might be affecting you, as I gather from your description) is having a stateful widget nested inside another stateful widget.

For instance,

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(...);
  }

  (...)
}

The problem here is that a rebuild of Parent means that ParentState().build() is run, and a new Child instance is created, with a new ChildState object. Which resets everything.

Try not recreating ChildWidget, but instead saving it on ParentState, like so:

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: You just need to remember that, if your widget tree is a bit more complex, you may need to 1) pass a callback from the Parent to notify of state changes, and 2) not forget to also call setState() on the Child.

like image 159
rbp Avatar answered Sep 20 '22 08:09

rbp


you just need make a new class and import that on your target class that seen problem. for example :

I usually create a class like this :

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

and

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

that's it.

like image 30
Sina.Moradbakhti Avatar answered Sep 20 '22 08:09

Sina.Moradbakhti


hi dont use Scaffold key i.e

    Scaffold (
    ...
    key: _scaffoldKey, //remove this
    ...
    )

on the page and do a complete page rebuild (not hot reload), and you should be fine worked for me tho!

like image 28
The Billionaire Guy Avatar answered Sep 21 '22 08:09

The Billionaire Guy