Reputation: 253
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
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
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
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
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
Reputation: 27177
you have to declare _formKey as static outside of build method.
Upvotes: 20