键盘弹出时如何让Flutter Column内容在可用区域居中?
问题:键盘弹出时Column内容未在可用区域居中,如何实现y1等于y2?
在真机上打开键盘后,当前代码中的Column会以屏幕整体高度居中,而非键盘弹出后的可用区域内居中,导致输入框距离顶部的y1和距离键盘顶部的y2不相等。需要实现键盘弹出时y1等于y2的效果。
原代码:
@override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Padding( padding: const EdgeInsets.all(8.0), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ TextField( keyboardType: TextInputType.number, decoration: InputDecoration( labelText: 'Input box for keyboard test', ), autofocus: true, focusNode: _textFieldFocus, //dont forget this parameter onSubmitted: (value) { // print("$value"); FocusScope.of(context).requestFocus(_textFieldFocus); }, ), ], ), ), ), ); }

解决方案
要实现键盘弹出时输入框在可用区域垂直居中(y1等于y2),可以用以下几种方法:
方法1:用MediaQuery计算可用高度
通过MediaQuery.of(context).viewInsets.bottom获取键盘高度,算出当前屏幕的可用高度,再把Column放在这个高度的容器里居中,就能让输入框始终处于剩余空间的中间位置。
修改后代码:
@override Widget build(BuildContext context) { // 获取当前键盘高度 final keyboardHeight = MediaQuery.of(context).viewInsets.bottom; // 计算可用高度:屏幕总高度 - 键盘高度 final availableHeight = MediaQuery.of(context).size.height - keyboardHeight; return Scaffold( body: SafeArea( child: Padding( padding: const EdgeInsets.all(8.0), child: Container( height: availableHeight, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ TextField( keyboardType: TextInputType.number, decoration: InputDecoration( labelText: '输入框键盘测试', ), autofocus: true, focusNode: _textFieldFocus, onSubmitted: (value) { FocusScope.of(context).requestFocus(_textFieldFocus); }, ), ], ), ), ), ), ); }
方法2:用SingleChildScrollView适配布局
把Column放在SingleChildScrollView里,设置Column的mainAxisSize为MainAxisSize.min,再用Center包裹。这样键盘弹出时,SingleChildScrollView会自动调整可用空间,让输入框保持居中。如果不需要滚动,可以加上NeverScrollableScrollPhysics()禁止滚动。
修改后代码:
@override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Padding( padding: const EdgeInsets.all(8.0), child: SingleChildScrollView( physics: const NeverScrollableScrollPhysics(), // 仅利用布局调整,禁止滚动 child: Center( child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.center, children: [ TextField( keyboardType: TextInputType.number, decoration: InputDecoration( labelText: '输入框键盘测试', ), autofocus: true, focusNode: _textFieldFocus, onSubmitted: (value) { FocusScope.of(context).requestFocus(_textFieldFocus); }, ), ], ), ), ), ), ), ); }
方法3:用LayoutBuilder动态获取布局约束
LayoutBuilder能实时获取父容器的约束,直接用约束的最大高度来布局,适配性更强,适合复杂的布局场景。
修改后代码:
@override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Padding( padding: const EdgeInsets.all(8.0), child: LayoutBuilder( builder: (context, constraints) { return SizedBox( height: constraints.maxHeight, child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ TextField( keyboardType: TextInputType.number, decoration: InputDecoration( labelText: '输入框键盘测试', ), autofocus: true, focusNode: _textFieldFocus, onSubmitted: (value) { FocusScope.of(context).requestFocus(_textFieldFocus); }, ), ], ), ); }, ), ), ), ); }
内容的提问来源于stack exchange,提问作者rozerro
相关产品推荐
相关产品推荐

