赞
踩
事情是这样的,由于近期 Flutter 发布了 1.17
的稳定版,按照“惯例”开始着手把生产项目升级到 1.12.13+hotfix.9
版本,在升级适配完成之后,一个突如其来的 Bug 让我陷入了沉思。
如上图所示,可以看到在键盘 B 页面打开后,退回上一个页面 A 时键盘已经收起,但是原先键盘所在的区域在 A 页面变成了空白,而 A 页面内容也被 resize
成了键盘弹出后的大小。
针对这个问题,首先想到的 Scaffold
的 resizeToAvoidBottomInset
属性。
在 Flutter 中 Scaffold
默认情况下 resizeToAvoidBottomInset
为 true
,当 resizeToAvoidBottomInset
为 true
时,Scaffold
内部会将 mediaQuery.viewInsets.bottom
参与到 BoxConstraints
的大小计算,也就是键盘弹起时调整了内部的 bottom
位置来迎合键盘。
但是问题发送在 A 界面,这时候键盘已经收起,mediaQuery.viewInsets.bottom
应该更新为 0 ,那为何界面没有产生应有的更新呢?
那么猜测问题可能出现在 MediaQuery
上。
从源码我们得知 MediaQuery
是一个 InheritedWidget
,它会往下共享对应的 MediaQueryData
,在 MediaQueryData
中保存了各种设备的信息,比如 size
、devicePixelRatio
、 textScaleFactor
、 viewPadding
以及 viewInsets
等。
那 viewInsets
是什么的呢?官方的解释是:
“可以被系统显示的区域,通常是和设备的键盘等相关,当键盘弹出时
viewInsets.bottom
对应的就是键盘的顶部。”
那上面的 bug 看起来可能就是 Scaffold
的 viewInsets.bottom
在键盘收起来时没有正常重置。
那这里首先我们要知道 MediaQuery
的 viewInsets
是怎么被设置的?
通过分析源码可以知道 MediaQuery
的 MediaQueryData
来源于 WidgetsBinding.instance.window
,默认是在 Materia
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。