记录一下开发过程中的问题
在开发过程中可能会遇到这样的场景,一个列表上有很多个输入框组件,可以编辑,也可以上下滑动,底部还有个固定的按钮,一般都是通过Stack、Positioned层叠定位布局固定到底部实现的,会遇到2种情况:
第一种:自带的这种,Scaffold默认会打开重新计算View高度的设置,即resizeToAvoidBottomInset默认为true,这种方式会有个不好地方,就是当键盘弹出来的时候会把底部按钮顶上去,原生就很容易解决这种问题。在flutter可以通过显示隐藏来解决或者问题,但是这种方式在收起键盘的时候在安卓机上有明显的卡顿留白,很难受
Stack(
fit: StackFit.expand,
children: [
_content(),
Positioned(
left: 0,
right: 0,
bottom: 0,
child: Visibility(
visible: MediaQuery.of(context).viewInsets == EdgeInsets.zero,
child: _bottomLayout(),
),
),
],
)
第二种:在Scaffold中设置resizeToAvoidBottomInset为false,让页面在弹出收起键盘的时候不重新绘制,这个时候又有了新的问题,底部按钮正常固定在底部,但是输入框会被键盘遮挡住,就需要做处理让其滚动到键盘上方。我是这么解决的,给每个item设置GlobalKey和FocusNode,设置GlobalKey是为了获取输入框在获取item所在屏幕的坐标
Scaffold(
resizeToAvoidBottomInset: false,
)
计算item所在位置
extension GlobalKeyExtension on GlobalKey {
Rect? get globalPaintBounds {
final renderObject = currentContext?.findRenderObject();
var translation = renderObject?.getTransformTo(null).getTranslation();
if (translation != null && renderObject?.paintBounds != null) {
return renderObject?.paintBounds.shift(Offset(translation.x, translation.y));
} else {
return null;
}
}
}
FocusNode是为了监听TextField获取焦点并计算所在位置
focusNode.addListener(() {
offsetY=containerKey.globalPaintBounds?.bottom ?? 0;
});
接下来with WidgetsBindingObserver添加监听,实现didChangeMetrics方法,didChangeMetrics这个方法是在页面尺寸发生变化时会调用,可以在这个方法里面做列表的滚动处理,然后通过ScrollController的animateTo方法让item滚动到键盘上方
@override
void didChangeMetrics() {
// 获取页面高度
var pageHeight = MediaQuery.of(getCurContext()).size.height;
if (pageHeight <= 0) {
return;
}
final keyboardTopPixels = window.physicalSize.height - window.viewInsets.bottom;
final keyboardTopPoints = keyboardTopPixels / window.devicePixelRatio;
// 计算出软键盘高度
final keyboardHeight = pageHeight - keyboardTopPoints;
if(offsetY < (pageHeight-keyboardHeight || keyboardHeight <= 0)){
return;
}
//要滑动高度
final scrollHeight =keyboardHeight - (pageHeight - offsetY) + scrollController.offset;
if (scrollHeight > 0) {
scrollController.animateTo(
scrollHeight, duration: Duration(microseconds: 200),curve: Curves.ease,
);
}
}
如有不足之处,还请指正,谢谢!