单击TextField小部件时重新构建Flutter小部件

时间:2019-04-02 12:15:11

标签: dart flutter

我确定这是一个菜鸟错误,但是我似乎无法弄清楚。 在下面的应用程序中,单击第二条路径中的文本字段时,键盘将打开并立即关闭。经过仔细调查,似乎只要获得焦点,便会重新构建该小部件,从而导致路由重置,从而使用户无法输入文本。

当我从表单中删除“键”时,不会发生此问题。这不是一项长期解决方案,因为我需要“密钥”,因此我可以验证表单。

有什么想法吗?

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

4 个答案:

答案 0 :(得分:0)

您必须在构建方法之外将 _formKey 声明为静态。

答案 1 :(得分:0)

当您单击到TextField时,Flutter会重新声明您的_formKey。因此,它会导致重新构建窗口小部件。您需要在_formKey方法外部声明build,以便Flutter不会重新声明您的变量。

答案 2 :(得分:0)

当我们单击java.lang.AssertionError: expected: Success(data=Rates(#5)) (class: Success) but was: [] (latch = 1, values = 0, errors = 0, completions = 0, timeout!) Expected :Success(data=Rates(#5)) (class: Success) Actual :[] (latch = 1, values = 0, errors = 0, completions = 0, timeout!) <Click to see difference> at io.reactivex.observers.BaseTestConsumer.fail(BaseTestConsumer.java:189) at io.reactivex.observers.BaseTestConsumer.assertValue(BaseTestConsumer.java:354) 时,颤振会自动调用TextField方法,因此您的所有对象都将重新创建,并在build()方法中进行初始化。

这就是为什么总是创建在build()中使用的全局变量,如:

Form()

答案 3 :(得分:0)

如果您的屏幕依赖MediaQuery至少一个 小部件依赖于 MediaQuery,则键盘弹出窗口更改屏幕的大小,这会触发 mediaQuery 并导致重建...在这种情况下,请避免使用 mediaQuery,而是使用 (sizer 包) https://pub.dev/packages/sizer