有没有一种方法可以帮助键盘正确地聚焦在 textformfield 上

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

我用 flutter 编写了一个 android 应用程序。作为我代码的一部分,我创建了一个用户页面,让用户可以更新他们的信息,例如姓名或类似的信息。

它工作正常,但是当我点击该页面时,出现了一些错误。

1 is I/ple.flutter_ap(18747): ClassLoaderContext 是一个特殊的共享库。

2nd is W/ple.flutter_ap(18747): Accessing hidden field Ldalvik/system/BaseDexClassLoader;->pathList:Ldalvik/system/DexPathList; (浅灰名单,反射)

另一个问题是键盘没有聚焦在文本字段上。当我单击文本字段时,键盘会立即打开和关闭。当我再次点击时,它出现并立即关闭。

我试过 autofocus: true 但这次它试图自己对焦。它被打开和关闭 5 次,但最后它集中了。但那不应该发生。

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);
                          },
                        ),
                      ],
                    );
                  },
                );
              })
      )
  );
}
}

如何解决这个问题?

要关注下一个文本输入字段,您必须使用“FocusNode();”,如下所示: 在"TextFormField("中我们可以使用这种方法来聚焦:

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

同时为文本输入字段设置不同的选项,例如键盘中的下一步和完成选项,您可以使用以下方法:

1) 对于下一个选项:"textInputAction: TextInputAction.next,"

2) 对于完成选项:"textInputAction: TextInputAction.done,"

下面是自动聚焦到下一个文本输入字段的完整示例:

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);
                      },
                    ),
                  ),


                ],

              ),

            ),
        ),

    );
  }

}

问题是您在使用 TextEditingController 打开键盘时在 TextFormField 中设置文本。 这意味着 您每次都在 TextEditingController 中分配一个值,因此当键盘打开时,"TextEditingController" 将 开火,它会尝试检查您的情况并在您的 TextFormField 中设置默认值,然后键盘获取 正常关闭。

所以要解决这个问题,请执行以下操作:

首先使用 "new" 键盘初始化您的 "TextEditingController",如下所示:

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

然后尝试在这两行之后为 "TextFormField" 设置默认文本:

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

然后如下更改 "TextFormField" 并尝试将这些值保存在 "onSubmitted" 方法中的变量中:

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);
                          },
                        ),
                      ],
                    );

如果上述解决方案不起作用,请尝试使用 StreamBuilder() 而不是 FutureBuilder()。它将毫无问题地工作和聚焦。