Pat J
Pat J

Reputation: 253

Flutter widget rebuilding when TextField widget clicked

I'm sure this is a rookie error however I can't seem to figure this one out. In the app below, when the textfield in the second route is clicked the keyboard opens and immediately closes. On closer investigation it seems that the widget is being rebuilt whenever it gets focus, causing the route to reset, making it impossible for the user to enter text.

When I remove the "key" from the form the problem doesn't occur. This isn't a long term fix as I need the "key" so I can validate the form.

Any ideas?

import 'package:flutter/material.dart';


void main() => runApp(MyApp());

class MyApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My app',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.lightBlue,
        fontFamily: 'Nunito',
      ),
      home: LoginPage(),
    );
  }
}


class LoginPage extends StatefulWidget {

  @override
  LoginPageState createState() {
    return new LoginPageState();
  }
}

class LoginPageState extends State<LoginPage> {

  Widget build(BuildContext context) {

    final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();

    final registerButton = Padding(
      padding: EdgeInsets.symmetric(vertical: 16.0),
      child: RaisedButton(
        shape: RoundedRectangleBorder(
          borderRadius: BorderRadius.circular(24),
        ),
        onPressed: () {
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => SecondPage()),
          );
        },
        child: Text('Register Now', style: TextStyle(color: Colors.white)),
      ),
    );

    // Now load the main login page
    return Scaffold(
      backgroundColor: Colors.white,
      key: _scaffoldKey,
      body: Center(
        child: ListView(
          shrinkWrap: true,
          children: <Widget>[
            registerButton,
          ],
        ),
      ),
    );
  }
}


class SecondPage extends StatelessWidget {

  @override
  Widget build(BuildContext context) {

    final emailController =  TextEditingController();
    final _formKey = GlobalKey<FormState>();

    final email = TextFormField(
      keyboardType: TextInputType.emailAddress,
      controller: emailController,
      autofocus: false,
      decoration: InputDecoration(
        hintText: 'Email',
        contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),
        border: OutlineInputBorder(borderRadius: BorderRadius.circular(32.0)),
      ),
    );

    return Scaffold(
      appBar: AppBar(
        title: Text('Second page'),
      ),
      body: Center(
        child: Form(
          key: _formKey,
          child: email,
        ),
      ),
    );
  }
}

Upvotes: 24

Views: 19946

Answers (5)

Muhammad Nadeem
Muhammad Nadeem

Reputation: 320

This strange behavoiur of media query when we click on textfield and keyBoard open media query rebulid one more same page in stack.

MaterialApp( useInheritedMediaQuery: true,)

useInheritedMediaQuery to true.

Upvotes: 0

Ahmed Salah
Ahmed Salah

Reputation: 151

if your screen depends on MediaQuery or at least having one widget depenig on MediaQuery, the keyboard popup changes the size of your screen, which triggers mediaQuery and causing rebuilds...in this case avoid using mediaQuery, Instead get your dimensions using (sizer package) https://pub.dev/packages/sizer

Upvotes: 15

Sanjayrajsinh
Sanjayrajsinh

Reputation: 17219

When we click on TextField then build() method is called automatically by flutter so your all object is recreate which initialise within build() method.

That's why always create global variable which is used in Form() like :

final emailController =  TextEditingController();
final _formKey = GlobalKey<FormState>();

Upvotes: 6

t13n
t13n

Reputation: 362

When you click to TextField, Flutter redeclare your _formKey. So it cause to rebuild your widget. You need to declare _formKey outside the build method so Flutter will not redeclare your variable.

Upvotes: 2

Viren V Varasadiya
Viren V Varasadiya

Reputation: 27177

you have to declare _formKey as static outside of build method.

Upvotes: 20

Related Questions