flutterkeyboardtextfieldlost-focus

Is there a way which helps the keyboard focus correctly on the textformfield


I write an android app with flutter. As a part of my code I created a user page to let the user to update their information such as name surname or something like that.

It is working but when I clicked the page I am getting few errors.

1 is I/ple.flutter_ap(18747): The ClassLoaderContext is a special shared library.

2nd is W/ple.flutter_ap(18747): Accessing hidden field Ldalvik/system/BaseDexClassLoader;->pathList:Ldalvik/system/DexPathList; (light greylist, reflection)

And the other problem is The keyboard is not focusing on the textfield. When I clicked the textfield the keyborad is Opening and closing immediately. When I clicked again it shows up and again closing immediately.

I tried autofocus: true but this time it tried to focus it self. It is opended and closed 5 times but at last it focused. But that shouldnt be happen.

import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

class Screen1 extends StatefulWidget {
  @override
  _Screen1State createState() => _Screen1State();
}

class _Screen1State extends State<Screen1> {


  var _AdContr = TextEditingController();
  var _SoyadContr = TextEditingController();
  final _NicknameContr = TextEditingController();
  final _getContr = TextEditingController();
  final _myUpdateContr = TextEditingController();

  var _transactionListener;

  @override
  void dispose() {
     // Clean up controllers when disposed
    _AdContr.dispose();
    _SoyadContr.dispose();
    _NicknameContr.dispose();
    _getContr.dispose();
    _myUpdateContr.dispose();
    // Cancel transaction listener subscription
    _transactionListener.cancel();
    super.dispose();
  }


  void clickUpdate(_formKey1, _formKey2) async {
    FirebaseUser user = await FirebaseAuth.instance.currentUser();
    String uid = user.uid.toString();
    await Firestore.instance
        .collection('kitaplar')
        .document(uid)
        .updateData({'adi': _formKey1, 'Soyadi': _formKey2});
    Navigator.pop(context);
  }



  @override
  void initState() {
    super.initState();


  }    





   @override
   Widget build(BuildContext context) {
     return new Scaffold(
      appBar: AppBar(
        title: Text('Retrieve Text Input'),
      ),
      body: new Container(
          padding: EdgeInsets.only(top: 20.0, left: 10.0, right: 10.0),
          child: FutureBuilder(
              future: FirebaseAuth.instance.currentUser(),
              builder: (BuildContext context,
                  AsyncSnapshot<FirebaseUser> snapshot) {
                if (snapshot.connectionState != ConnectionState.done)
                  return Container();
                return StreamBuilder<DocumentSnapshot>(
                  stream: Firestore.instance.collection('kitaplar')
                      .document(snapshot.data.uid)
                      .snapshots(),
                  builder: (BuildContext context, AsyncSnapshot snapshot) {
                    if (!snapshot.hasData) return Container();
                    var userDocument = snapshot.data;
                    var contentadi = userDocument["adi"].toString();
                    var contentsoyadi = userDocument["Soyadi"].toString();

                    return Column(
                      children: <Widget>[
                        TextFormField(
                          controller: _AdContr = new TextEditingController(text: contentadi == null ? "" : contentadi),
                          //controller: _AdContr,
                          //initialValue: userDocument["adi"].toString(),
                          decoration: new InputDecoration(
                            labelText: 'Adınız',
                            fillColor: Colors.white,
                            border: new OutlineInputBorder(
                              borderRadius: new BorderRadius.circular(25.0),
                              borderSide: new BorderSide(),
                            ),
                            //fillColor: Colors.green
                          ),
                        ),
                        SizedBox(height: 20),
                        TextFormField(
                          controller: _SoyadContr = new TextEditingController(text: contentsoyadi == null ? "" : contentsoyadi),
                          //controller: _AdContr,
                          decoration: new InputDecoration(
                            labelText: 'Soyadınız',
                            fillColor: Colors.white,
                            border: new OutlineInputBorder(
                              borderRadius: new BorderRadius.circular(25.0),
                              borderSide: new BorderSide(),
                            ),
                            //fillColor: Colors.green
                          ),
                        ),
                        RaisedButton(
                          color: Colors.orange,
                          textColor: Colors.white,
                          splashColor: Colors.orangeAccent,
                          child: const Text('Update'),
                          onPressed: () {
                            clickUpdate(_AdContr.text, _SoyadContr.text);
                          },
                        ),
                      ],
                    );
                  },
                );
              })
      )
  );
}
}

How do I solve this problem?


Solution

  • To foucs on next text input field you have to use "FocusNode();" such as below: In the "TextFormField(" we can use this method to focus:

    onFieldSubmitted: (v){
          FocusScope.of(context).requestFocus(focus);
    },
    

    Also to set different options for text input field such as next and done options in keyboard, you can use below method:

    1) For next option: "textInputAction: TextInputAction.next,"

    2) For done option: "textInputAction: TextInputAction.done,"

    Below is the full example to auto focus on next text input field:

    class MyApp extends State<MyLoginForm> {
      final _formKey = GlobalKey<FormState>();
      final focus = FocusNode();
    
      @override
      Widget build(BuildContext context) {
        return Container(
            color: Colors.white,
            child: Center(
                child: Form(
    
                  key: _formKey,
                  child: Column(
    
                    mainAxisAlignment: MainAxisAlignment.start,
                    children: <Widget>[
    
                      Padding(
                        padding: const EdgeInsets.only(left: 30, top: 65.0, right: 30, bottom: 0),
                        child:
                        TextFormField(
                          textInputAction: TextInputAction.next,
                          decoration: new InputDecoration(hintText: 'Enter username', contentPadding: EdgeInsets.all(8.0)),
                          style: new TextStyle(fontSize: 18),
                          onFieldSubmitted: (v){
                            FocusScope.of(context).requestFocus(focus);
                          },
                        ),
                      ),
    
                      Padding(
                        padding: const EdgeInsets.only(left: 30, top: 30.0, right: 30, bottom: 0),
                        child:
                        TextFormField(
                          focusNode: focus,
                          textInputAction: TextInputAction.done,
                          decoration: new InputDecoration(hintText: 'Enter password', contentPadding: EdgeInsets.all(8.0)),
                          style: new TextStyle(fontSize: 18),
                          onFieldSubmitted: (v){
                            FocusScope.of(context).requestFocus(focus);
                          },
                        ),
                      ),
    
    
                    ],
    
                  ),
    
                ),
            ),
    
        );
      }
    
    }
    

    Problem is you are setting the text in TextFormField when keyboard opens with the TextEditingController. It means you are assigning a value every time in TextEditingController so when keyboard opens, "TextEditingController" will fire and it will try to check your condition and set the default value in your TextFormField and then keyboard gets closed as normal behaviour.

    So to solve this do as below:

    First of all initialize your "TextEditingController" with "new" keyboard as below:

      var _AdContr = new TextEditingController();
      var _SoyadContr = new TextEditingController();
      final _NicknameContr = new TextEditingController();
      final _getContr = new TextEditingController();
      final _myUpdateContr = new TextEditingController();
    

    Then try to set default text for "TextFormField" after this two lines:

    var contentadi = userDocument["adi"].toString();
    var contentsoyadi = userDocument["Soyadi"].toString();
    _AdContr.text = (contentadi == null ? "" : contentadi);
    _SoyadContr.text = (contentsoyadi == null ? "" : contentsoyadi);
    

    Then change your "TextFormField" as below and try to save those value in your variables in "onSubmitted" method:

    return Column(
                          children: <Widget>[
                            TextFormField(
                              controller: _AdContr,
                              onSubmitted: (String str){
                                setState(() {
                                    contentadi = str;
                                    _AdContr.text = contentadi;
                                });
                              },
                              decoration: new InputDecoration(
                                labelText: 'Adınız',
                                fillColor: Colors.white,
                                border: new OutlineInputBorder(
                                  borderRadius: new BorderRadius.circular(25.0),
                                  borderSide: new BorderSide(),
                                ),
                                //fillColor: Colors.green
                              ),
                            ),
                            SizedBox(height: 20),
                            TextFormField(
                              controller: _SoyadContr,
                              onSubmitted: (String str){
                                setState(() {
                                    contentsoyadi = str;
                                    _SoyadContr.text = contentsoyadi;
                                });
                              },
                              decoration: new InputDecoration(
                                labelText: 'Soyadınız',
                                fillColor: Colors.white,
                                border: new OutlineInputBorder(
                                  borderRadius: new BorderRadius.circular(25.0),
                                  borderSide: new BorderSide(),
                                ),
                                //fillColor: Colors.green
                              ),
                            ),
                            RaisedButton(
                              color: Colors.orange,
                              textColor: Colors.white,
                              splashColor: Colors.orangeAccent,
                              child: const Text('Update'),
                              onPressed: () {
                                clickUpdate(_AdContr.text, _SoyadContr.text);
                              },
                            ),
                          ],
                        );
    

    If above solution not work then try to use StreamBuilder() instead of FutureBuilder(). it will work and focuse without any problem.