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,
),
),
);
}
}
One of the easiest ways to avoid unwanted reBuilds that are caused usually by calling setState() in order to update only a specific Widget and not refreshing the whole page, is to cut that part of your code and wrap it as an independent Widget in another Stateful class.
Using setState to rebuild widgets Flutter gives you access to setState() . In this case, we have to ensure setState() has the new values. When setState() is called, Flutter will know to get these new values and mark the widget that needs to be rebuilt.
the only reason why your widgets got rebuilds after keyboard pop up. is that one or more of your widgets size depends on MediaQuery. you can try to ge your screen size from LayoutBuilder as an alternative for MediaQuery.
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
you have to declare _formKey as static outside of build method.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With