如何避免键盘弹出时重新加载整个页面?

时间:2019-08-08 09:36:21

标签: android flutter dart

观看此视频以获取问题演示 https://youtu.be/GsdWcTEbUbg

由于存在大量代码,因此我将在此处尝试总结代码的结构。 简而言之:

Scaffold(
  appBar: AppBar(),
  body: StreamBuilder<dynamic>(
    stream: globals.chatRoomBloc.threadScreen,
    builder: (BuildContext context, AsyncSnapshot snapshot) {
      return Column(
        crossAxisAlignment:
            CrossAxisAlignment.stretch, // sticks to the keyboard
        children: <Widget>[
          Expanded(
            child: Scrollbar(
              child: ListView.builder(
                shrinkWrap: true,
                itemCount: list.length,
                itemBuilder: (BuildContext context, int index) {
                  return TileWidget();
                },
              ),
            ),
          ),
        ],
      );
    },
  ),
)

TileWidget是有状态的,当按下回复按钮时,将附加TextField并调整窗口小部件的大小。然后,当用户单击“文本字段”时,将弹出键盘。

现在我的问题是,键盘弹出时屏幕会重新加载。

我尝试了以下解决方案:

  1. Using TextField inside a Streambuilder:我只设置一次流,即第一次加载页面时。添加新的聊天或条目后,将对流进行任何更改。就我而言,这不会发生。
  2. Flutter Switching to Tab Reloads Widgets and runs FutureBuilder我不确定这是否是相同的问题,但是解决方案对我来说并没有任何改变。
  3. Issue #11895-我也经历了这一点,但没有帮助。

我认为屏幕正在尝试调整大小并重新绘制以适应键盘抽屉。但这是由于某种原因而无法执行此操作并重新加载所有内容。我想念什么吗?有办法解决吗?

1 个答案:

答案 0 :(得分:0)

您提供的链接之一指出,只要应用程序的状态发生变化(即键盘弹出),构建方法就会触发,因此将streambuilder移出它。您还可以进行其他更改。尝试以下操作,

在build方法之外创建一个变量。

const loginForm: FormData = new FormData();
loginForm.append('username', form.username);
loginForm.append('password', form.password);
loginForm.append('submit', 'login');
return this.http.post(<my_login_url>, loginForm)

然后在您的构建方法中调用该变量。

var myStreamBuilder;
//....
//inside initialstate method
     myStreamBuilder = StreamBuilder<dynamic>(
            stream: globals.chatRoomBloc.threadScreen,
            builder: (BuildContext context, AsyncSnapshot snapshot) {
              return Column(
                crossAxisAlignment:
                    CrossAxisAlignment.stretch, // sticks to the keyboard
                children: <Widget>[
                  Expanded(
                    child: Scrollbar(
                      child: ListView.builder(
                        shrinkWrap: true,
                        itemCount: list.length,
                        itemBuilder: (BuildContext context, int index) {
                          return TileWidget();
                        },
                      ),
                    ),
                  ),
                ],
              );
            },
          ),

编辑:请确保您检查快照是否具有data。如果没有数据,则应返回某些内容,直到它包含数据为止,这样可以通知用户应用程序在做什么。

此属性也可能对您有所帮助。 resizeToAvoidBottomInset-https://api.flutter.dev/flutter/material/Scaffold/resizeToAvoidBottomInset.html