Flutter: keyboard disappears immediately when editing my text fields
Asked Answered
W

19

60

Sign up form with flutter

I'm trying to build an app front end with flutter and it's my first time so I faced some bugs like this one: there is no way to edit my textformfield because I putted my form elements in a listview ! when keyboard appears to enter some text to the field it disappears in a second ! I need an immediat solution please :(

import 'package:flutter/material.dart';
import'package:dubai274_app/mobile_verif.dart';
import 'EnsureVisible.dart';
class SignUp extends StatefulWidget{
  static String tag = 'Sign_up-page';
  SignUp_Page createState() => SignUp_Page();

}
class SignUp_Page extends State<SignUp>{
  


  List<DropdownMenuItem<String>> _Dropdownmenuitems;
  String _statusSel;
  List<DropdownMenuItem<String>> _getDropdownmenuitem(){

    List<DropdownMenuItem<String>> items=new List();
    items.add(new DropdownMenuItem(value:'Emirates',child: new Text('United Arab Emirates')));
    items.add(new DropdownMenuItem(value:'Tun',child: new Text('Tunisia')));
    return items;
  }
  void changeddropdowselecteditem(String selecteditem){
    setState(() {
_statusSel=selecteditem;
    });
  }
   @override
  void initState() {
    // TODO: implement initState
    //listViewController=new ScrollController().addListener(_scrollListener);
    _Dropdownmenuitems=_getDropdownmenuitem();
    _statusSel=_Dropdownmenuitems[0].value;
  }
@override
  Widget build(BuildContext context) {
  final scaffoldKey = GlobalKey<ScaffoldState>();
  final formKey = GlobalKey<FormState>();
  final TextEditingController _controller = new TextEditingController();
  
final first_value=TextFormField(autofocus: false,
  validator: (val) =>
  val.length < 6 ? 'First name required' : null,
  decoration: InputDecoration(
    labelText: 'First Name',
    hintText: 'First Name',
    contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),


  ),);

final family_value=TextFormField(autofocus: false,
  decoration: InputDecoration(
    labelText: 'Last Name',
    hintText: 'Last Name',
    contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),


  ),);

final Nationality=new DropdownButton(items: _Dropdownmenuitems, value:_statusSel,onChanged: changeddropdowselecteditem);

final email_value=TextFormField(keyboardType: TextInputType.emailAddress,
  autofocus: false,
  decoration: InputDecoration(
    labelText: 'Email',
    hintText: 'Email',
    contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),

  ),);

final password=Column(children: <Widget>[ TextFormField(autofocus: false,

  obscureText: true,
  decoration: InputDecoration(
    labelText: 'Password',
    hintText: 'Password',
    contentPadding: EdgeInsets.fromLTRB(20.0, 10.0, 20.0, 10.0),)), Text('Min 8 characters with at least one special character')]);
  void _performsignup() {

    final snackbar = SnackBar(
      content: Text('Email: $email, password: $password'),
    );

    scaffoldKey.currentState.showSnackBar(snackbar);
  }
  void _submit() {
    final form = formKey.currentState;

    if (form.validate()) {
      form.save();
      Navigator.push(
        context,
        MaterialPageRoute(builder: (context) => MobileVerif()),
      );

      _performsignup();
    }
  }
final forward_signedin=FloatingActionButton(tooltip: 'Go forward',
  child: Icon(Icons.arrow_forward,color: Colors.white,size: 38.4,),


  onPressed: (){_submit();},);

return MaterialApp(
      title: 'Sign_Up_Page',
      home: Scaffold(
        appBar: AppBar(
          elevation: 0.0,
      backgroundColor: Colors.transparent,
      title: const Text('Sign Up',style: TextStyle(color: Colors.blueAccent, fontSize: 25.0,fontWeight: FontWeight.bold),textAlign: TextAlign.center,),
  centerTitle: true,
  leading: IconButton(
  tooltip: 'Previous choice',
  icon: const Icon(Icons.arrow_back_ios),
    onPressed: () { Navigator.pop(context);},
    color: Colors.black,
    iconSize: 20.0,
  ),
  ),
        body: new Container(
          decoration: new BoxDecoration(
          image: new DecorationImage(
            image: new AssetImage("assets/background.png"),
            fit: BoxFit.cover,
          ),
        ),
        child: new Form( key: formKey,
            child: new Padding( padding: new EdgeInsets.all(40.0), child: ListView(
      children: <Widget>[

       first_value,
       family_value,
       Nationality,
       email_value,
       password,
       new ListTile( title:forward_signedin,)],
)) )

        ),


        ),

      );


  }
}
Where answered 13/7, 2018 at 8:19 Comment(2)
we can't know the problem if you don't share what you have tried so farCarlsen
@Farah, did you find a solution?Palish
D
109

You have the following code in your build function:

final formKey = GlobalKey<FormState>();

This is the problem. You have to either make it static or move to initState()

Deictic answered 18/3, 2019 at 14:43 Comment(5)
I ran into a similar issue. Basically, I have a form that I wanted to reuse so I created a separate widget. Then from wherever I use that widget, I passed down the GlobalKey<FormState> to the widget. One form would work fine and the other would exhibit the keyboard dismissal behavior. However, the creation of the key was NOT in the build method. Creating the key as static as you suggested seemed to fix it but no clue why...Culvert
anyone care to explain why this is happening when not declaring it into static?Maiocco
This happens when you put GlobalKey<FormState> in your build functionHoban
Static makes it have no business to do with the class' activites @Moralde-Sama. can anyone push this explanation further?Fabulist
Exactly my problem, had the formKey in Widget build(BuildContext context) insted of my StatefulWidget's class _MyClassState extends State<MyClass>Fineman
D
28

I had the same problem and as @apc said just make the key static or intialize it in iniState()...

if you use stateless widget make it static

static final GlobalKey<FormState> _key = GlobalKey<FormState>();

Dickie answered 19/10, 2020 at 11:59 Comment(1)
This fixed my issue, thanksAggappe
G
16

Having a GlobalKey for the form didn't do it for me. What helped was this github comment. Essentially, having a MediaQuery.of(context) for getting the size of the screen causes rebuilds that make the textfield lose focus. In my case, the MediaQuery accessing widget was very high up the widget tree. I had to look it up and replace it with LayoutBuilder.

class ScreenSizeGetter extends StatelessWidget {
  const ScreenSizeGetter({Key? key, required this.child}) : super(key: key);
  final Widget child;

  @override
  Widget build(BuildContext context) {
    return LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) {
          double screenWidth = constraints.maxWidth;
          double screenHeight = constraints.maxHeight;
          
          // Can pass these sizes down to the child by Bloc pattern or other ways
          return child;
      },
    );
  }
}
Graner answered 25/3, 2022 at 10:32 Comment(1)
This was the issue for me! I replaced my MediaQuery.of(context).size.width with a LayoutBuilder and viewportConstraints.maxWidthKillerdiller
N
13

If you are using StatelessWidget, transform it into StatefulWidget. Make sure the key is state's property, not widget's. This happens because your form key is getting recreated over and over again with each rebuild. To keep the key, it should be a part of state.

Nidorf answered 1/6, 2020 at 1:5 Comment(0)
I
7

I'm going to post my answer here, even though it is not exactly the same as problem as the OP.

I searched the internet high and low for this issue of the keyboard appearing and disappearing, and
1. this was the only SO question I found that describes the keyboard appear disappear issue, and
2. the other solutions out there, like @apc's answer and this github answer are all focused on the formKey being static and/or a GlobalKey, and that was definitely not the cause of my problem (having unchanging keys or re-created keys for my form, and/or it's fields, had no effect at all on the issue).

My specific problem involved a class AuthService with ChangeNotifier with a number of Future methods.
After literally days of trying different approaches I found that the only way that I could avoid the keyboard-appearing-and-instantly-disappearing-on-form-field-focus issue was to have the AuthService() be at the top level of my app, in runApp() :

void main() => runApp(
  ChangeNotifierProvider<AuthService>(
    child: TheWidgetThatIsMyAppAndHasAllBusinessLogicInIt(),
    builder: (BuildContext context) {
      return AuthService();
    },
  ),
);

(Having the ChangeNotifierProvider anywhere else in the code has the keyboard disappear issue)

I've then had to get creative about how I structured my logic under this - because I only really care about the AuthService in certain parts of my application, but I'm very new to Flutter and it's all been good learning.

I don't know why this is, and I'd love to learn more, and I know I haven't spelled out my full situation.....
but I've spent literally days solving this, I needed to put my answer here to hopefully help others.

Invective answered 27/10, 2019 at 0:40 Comment(3)
builder is now depracted. Please use create insteadJesus
The problem can also be caused by calling setState() within TextController.addListener() or the TextField's onChanged() method when the TextField is a descendant of VisibilityDetector.Jefferson
When I call the notifyListeners() method in the TextField onChanged event, I encounter the problem that the keyboard closes. making formkey static final solves the problem of closing the keyboard. However, when I press the back key and reopen the form, the values in the textField are not cleared, although I reset the values in the provider. I think that the value in the TextEditingController is not cleared. I didn't have such a problem when I defined Formkey in my build method. Why does the problem arise and how can I solve this problem?Abrasive
T
5

You should define all of the these:

  final scaffoldKey = GlobalKey<ScaffoldState>();
  final formKey = GlobalKey<FormState>();
  final TextEditingController _controller = new TextEditingController();

as fields of the SignUp_Page not at build function.

Tunable answered 9/11, 2020 at 7:37 Comment(0)
I
3

In my case the problem had two parts:

  1. The TextField had a FutureBuilder above it in the StatefulWidget's build tree.
  2. The TextField called setState in its onChanged event handler.

It seems every time setState was called the FutureBuilder rebuilt its tree, causing the TextField to lose focus. I moved the FutureBuilder up the tree so it was outside the StatefulWidget and the problem disappeared.

Inadvertency answered 10/9, 2022 at 3:36 Comment(0)
L
2

I had the similar problem. Mine problem was that I had MediaQuery.of... somewhere above the form in widget tree which caused multiple rebuilds when keyboard pops up. Even it would erase textEditingData in my textEditingControllers (using flutter hooks). The solution for me was to change MediaQuery.of to MediaQuery.sizeOf, MediaQuery.viewInsetsOf ...

Lynellelynett answered 6/11, 2023 at 12:21 Comment(0)
S
1

In my own case, I had this key: ValueKey<int>(math.Random().nextInt(5)), as the key for an ancestor widget of the TextFormField. I removed it and the error no longer appeared. So my debug suggestion is to check all widgets, in the widget tree, that has any value passed for its key argument..

Shantae answered 5/7, 2021 at 11:13 Comment(0)
A
0

If your TextField is in a Dismissible() widget then this cause the problem!

Alphabetical answered 24/9, 2021 at 19:2 Comment(0)
O
0

FWIW my issue was different than the accepted answer. I was refactoring code and accidentally copied a Key value into two places, so I had two text fields w/ the same key. This resulted in the behavior described by OP. By ensuring all of my Widget keys were unique, I was able to resolve this issue.

Orelle answered 25/1, 2022 at 12:37 Comment(0)
R
0

FWIW+1: I was using Router with Beamer and the page on top of the stack was not const. Const'ing the top page resolved it. No other change, just a const keyword in front of the Page on top of the stack...

Rochester answered 18/3, 2022 at 9:43 Comment(0)
S
0

After hours of research the solution that worked for me is to put the declaration of my Texteditindcontroller in static final and outside of my build method, i.e. just after the declaration of my class which extends to stateless widget

Sarver answered 23/3, 2022 at 14:15 Comment(0)
S
0

For anyone using multiple dynamically produced TextField:

I still faced errors even if I use a UniqueKey on Dismissible.

I then used Key(MyObject[index].id) with an ID using UUID to have unique keys that can be assigned to Dismissible, which led to the TextField closing upon taking in a single value (keyboard may be closing automatically due to touch events).

Finally, I switched to the Flutter_Swipable package, and that resolved my issue!

Shirberg answered 26/3, 2023 at 9:11 Comment(0)
P
0

This may be caused of the screen to be redrawn when the widget height is changed when the keyboard appears.

Look here for a solution suggestion to prevent the keyboard to alter (underneath) view size.

When the keyboard appears, the Flutter widgets resize. How to prevent this?

Phytobiology answered 27/3, 2023 at 11:48 Comment(0)
C
0

In my case the error was call to...

FocusScope.of(context).unfocus();

... when validate form without checking if the keyboard was or not visible. By comment that instruction the error disappears.

Clutch answered 30/4, 2023 at 11:58 Comment(1)
As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.Bobsled
F
0

simple if you are using a Stateless widget then just use static like this:

from

final GlobalKey _formKey = GlobalKey();

to

static final GlobalKey _formKey = GlobalKey();

and from

final TextEditingController _usernameController = TextEditingController();

to 

static final TextEditingController _usernameController = TextEditingController();

Firm answered 21/7, 2023 at 10:45 Comment(0)
R
0

For me, the issue was related to setting the background color of the TextField based on if the device was in light or dark mode using this:

Brightness get brightness {
  return MediaQuery.of(context).platformBrightness;
}

This was causing a rebuild because the size of the screen changes when the keyboard appears, and that means MediaQuery.of(context) has changed.

The solution was to use only query changes of the brightness instead:

Brightness get brightness {
  return MediaQuery.platformBrightnesssOf(context);
}
Remington answered 12/4 at 15:53 Comment(0)
G
-1

In my case, if I open the screen with Navigator.of(context).pushReplacementNamed(routeName), everything works fine.

If I use Navigator.of(context).pushNamed(routeName), the keyboard appears and then disappears instantly when I touch the TextFormField.

Goffer answered 1/6, 2023 at 20:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.