【问题标题】:Flutter TextFormField reloads current screen when focusedFlutter TextFormField 聚焦时重新加载当前屏幕
【发布时间】:2018-08-06 01:27:06
【问题描述】:

我有一个 TextFormField,当我点击它输入文本时它会重新加载当前屏幕。当我点击表单域时,软件键盘会在整个屏幕重新加载并再次呈现所有小部件之前短暂显示。我正在 Android 设备上运行该应用程序。

Container(
        child: Form(
          key: _formKey,
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: <Widget>[
              TextFormField(
                validator: (value) {
                  if (value.isEmpty) {
                    return 'Your input cannot be empty';
                  }
                },
              ),
              Padding(
                padding: const EdgeInsets.symmetric(vertical: 16.0),
                child: RaisedButton(
                  onPressed: () {

                    if (_formKey.currentState.validate()) {
                      print('validated');
                    }
                  },
                  child: Text('Save'),
                ),
              ),
            ],
          ),
        ),
        margin: EdgeInsets.only(top:8.0),
  ),

【问题讨论】:

  • 你在哪里声明了 _formKey 变量?
  • 我在与类属性/变量相同的类中声明了上面的 _formKey var。
  • @Amit 您需要使您的构建方法纯粹.. 键盘打开和关闭可以再次调用构建方法并因此呈现您的小部件。

标签: dart flutter


【解决方案1】:

问题是当您单击该字段时,TextFormField 的控制器正在重建,这就是您的问题的原因。

所以为了解决这个问题,您是否尝试创建一个 Statefull 小部件,然后在该小部件的状态中创建一个 TextEditingController 并将其作为参数传递给 TextFormField ?

【讨论】:

  • 这为我解决了。只需转换为有状态小部件并确保在状态中创建 TextEditingController。虽然我不是 100% 我理解为什么 TextEditingController 会被重建并重新初始化为其原始值......使其成为有状态的小部件修复它,谢谢
  • 这是因为无状态小部件在其父级调用构建方法时将完全重新构建。当我说完全时,我的意思是整个对象被重新实例化,并且通过这样做,它的所有字段都被重新创建...... StatefullWidget 类也是如此,但它的«child»类不是这样,State 类在其中我实际上声明了不会重新实例化的构建方法!你可以在网上找到很棒的文档、文章和视频!
  • 这很有帮助。我会进一步查找,谢谢!
【解决方案2】:

我遇到了同样的问题。这是我的代码

class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  Model model = Model();

  @override
  Widget build(BuildContext context) {
  GlobalKey<FormState> _formKey = GlobalKey<FormState>();
    var mediaWidth = MediaQuery.of(context).size.width / 2.0;
    return Scaffold(
...

我通过在构建方法之外声明 _formKey 解决了这个问题。这对我有用。

class MainPage extends StatefulWidget {
  @override
  _MainPageState createState() => _MainPageState();
}

class _MainPageState extends State<MainPage> {
  Model model = Model();
  GlobalKey<FormState> _formKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    var mediaWidth = MediaQuery.of(context).size.width / 2.0;
    return Scaffold(
...

希望对你有帮助

【讨论】:

    【解决方案3】:

    检查您是否在项目中错误地使用了 MediaQueries,我遇到了类似的问题,当我更改 MediaQuery 时它停止了 就我而言:

    Size _size = MediaQuery.of(context).size;
    

    删除这段代码修复了我的应用程序。

    【讨论】:

      【解决方案4】:

      TextFormField聚焦时,屏幕大小会因为键盘的出现而改变,导致状态重建,你不能阻止状态的重建。

      不要试图阻止重新构建状态,您需要解决状态重新构建时发生的问题,常见问题之一是build(BuildContext context){ ... }' 函数内的声明和初始化变量。 p>

      主要问题,当您需要获取一些与context 相关的数据(如屏幕大小)时,在这种情况下,我更喜欢从父级Widget 传递此值...

      例如这段代码在重新构建状态时会导致问题:

        @override
        Widget build(BuildContext context) {
          double? _screenHeight =  MediaQuery.of(context).size.height;
          return Container();
        }
      

      要解决问题,请从父母那里获得_screenHeight,要知道如何做到这一点,请查看https://stackoverflow.com/a/50289032/2877427

      【讨论】:

        【解决方案5】:

        是的,这是因为当键盘出现时,flutter 脚手架会调整为当前可用的屏幕尺寸。因此,我们可以通过防止脚手架尺寸变化来轻松处理这个问题。我建议将脚手架 resizeToAvoidBottomInset 属性设置为 false。如果是真的,主体和支架浮动小部件应自行调整大小,以避免屏幕键盘的高度由环境 MediaQuery 的、MediaQueryData、viewInsets 底部属性定义。

        解决方法:

        resizeToAvoidBottomInset: false,
        

        完整示例:

        @override
        Widget build(BuildContext context) {
          setDisplayData();
          return Scaffold(
            resizeToAvoidBottomInset: false,
            appBar: getAppBar(),
            body: OrientationBuilder(
              builder: (context, orientation) {
                return orientation == Orientation.portrait
                    ? _buildVerticalLayout()
                    : _buildHorizontalLayout();
              },
            ),
          );
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-01-11
          • 2022-12-06
          • 1970-01-01
          • 2020-02-02
          • 1970-01-01
          • 2020-08-22
          • 2022-11-01
          • 2020-12-13
          相关资源
          最近更新 更多