【问题标题】:Flutter - TextFormField resets page whenever keyboard pops upFlutter - 每当键盘弹出时,TextFormField 都会重置页面
【发布时间】:2021-08-24 16:35:00
【问题描述】:

我正在尝试使用 Flutter 框架通过 Firebase 构建登录页面,但每当我尝试使用 TextFormField 时,都会遇到屏幕重置问题,它会加载键盘,然后立即将我踢出去并重置页面。我查看了其他线程,但似乎找不到任何修复程序。感谢您提前提供的所有帮助!

class SignInTwo extends StatefulWidget {
  final Function toggleView;
  SignInTwo({this.toggleView});

  @override
  _SignInState createState() => _SignInState();
}

class _SignInState extends State<SignInTwo> {
  final AuthService _auth = AuthService();
  final _formKey = GlobalKey<FormState>();
  bool loading = false;

  // text fields state
  String email = "";
  String password = "";
  String error = "";

  @override
  Widget build(BuildContext context) {
    return loading ? Loading() : Scaffold(
      backgroundColor: Colors.brown[100],
      appBar: AppBar(
        backgroundColor: Colors.brown[400],
        elevation: 0.0,
        title: Text('Sign in'),
        actions: <Widget>[
          FlatButton.icon(
            label: Text("Register"),
            icon: Icon(Icons.person),
            onPressed: () {
              widget.toggleView();
            },
          )
        ],
      ),
      body: Container(
          padding: EdgeInsets.symmetric(vertical: 20.0, horizontal: 50.0),
          child: Form(
            key: _formKey,
            child: Column(
              children: <Widget>[
                SizedBox(
                  height: 20,
                ),
                TextFormField(
                  decoration: textDecoration.copyWith(hintText: 'Email'),
                  validator: (value) {
                    if (value.isEmpty) {
                      return 'Please enter email';
                    }
                    return null;
                  },
                  onChanged: (value) {
                    setState(() => email = value);
                  },
                ),
                SizedBox(
                  height: 20.0,
                ),
                TextFormField(
                  decoration: textDecoration.copyWith(hintText: 'Password'),
                  validator: (val) {
                    if (val.length < 6) {
                      return 'Enter password with more than 6+ characters';
                    }
                    return null;
                  },
                  onChanged: (value) {
                    setState(() => password = value);
                  },
                  obscureText: true,
                ),
                SizedBox(
                  height: 20.0,
                ),
                RaisedButton(
                  color: Colors.pink[400],
                  child: Text(
                    "Sign In",
                    style: TextStyle(color: Colors.white),
                  ),
                  onPressed: () async {
                    if (_formKey.currentState.validate()) {
                      setState(() {
                        loading = true;
                      });
                      dynamic result = await _auth.signInWithEmailAndPassword(
                          email, password);
                      if (result == null) {
                        setState(() {
                          error = "Something went wrong!!";
                          loading = false;
                        });
                      }
                    }
                  },
                ),
                SizedBox(
                  height: 20,
                ),
                Text(
                  error,
                  style: TextStyle(color: Colors.red),
                )
              ],
            ),
          )),
    );
  }
}

我不确定这是我的主要课程还是其他任何课程的问题,但我会将它们留在下面,以防它可能是问题的原因。

class MyApp extends StatefulWidget {
  final SharedPreferences storage;

  const MyApp({Key key, this.storage}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        fontFamily: "Audiowide",
        primarySwatch: Colors.yellow,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: Wrapper(),
    );
  }
}

这个包装器只是决定用户是否已经登录。在我的情况下,它不会返回 Authenticate 类。

class Wrapper extends StatelessWidget {
  @override
  Widget build(BuildContext context) {

    final player = Provider.of<Player>(context);

    if(player == null){
      return Authenticate();
    }else{
      return Home();
    }
  }
}

class Authenticate extends StatefulWidget {
  @override
  _AuthenticateState createState() => _AuthenticateState();
}

class _AuthenticateState extends State<Authenticate> {

  bool showSignIn = true;
  void toggleView() {
    setState(() {
      showSignIn = !showSignIn;
    });
  }

  @override
  Widget build(BuildContext context) {
    if(showSignIn){
      return SignInTwo(toggleView: toggleView);
    }else{
      return Register(toggleView: toggleView);
    }
  }
}

【问题讨论】:

    标签: flutter dart


    【解决方案1】:

    每次打开键盘时,都会调用 build 函数并检查它是否加载并创建新的 Scaffold 实例,这就是问题的原因 您可以通过向 Scaffold 添加密钥来修复它 像这样的

    Scaffold(key:scaffoldKey
    ...)
    

    【讨论】:

    • 我应该如何存储密钥?我真的是 Flutter 新手,以前从未使用过 key。