Flutter弹出键盘时如何防止背景图滚动并保持其位置与宽高比
解决方案
核心逻辑是将背景图和页面布局完全分离,背景固定撑满全屏,页面元素的滚动/resize不影响背景层:
- 根布局使用
Stack,第一层放背景图,用Positioned.fill强制占满整个屏幕空间,完全独立于上层页面逻辑 - 第二层放
Scaffold,背景设为透明,保持resizeToAvoidBottomInset为默认值true即可,不需要关闭 - 页面内容层包裹
SingleChildScrollView,保证键盘弹出时输入框可以自动滚动到可视区域
修改后的参考代码如下:
class LoginPage extends BasePage { LoginPage({Key? key}) : super(key, configTypes: [ConfigurationType.login]); @override State<LoginPage> createState() => _LoginPageState(); } class _LoginPageState extends BaseState<LoginPage> with BasicPage { @override Widget body() { return Stack( children: [ // 背景层:完全固定,不受键盘弹出影响 Positioned.fill( child: DecoratedBox( decoration: const BoxDecoration( image: DecorationImage( image: ExactAssetImage(Assets.bgLogin), fit: BoxFit.cover, alignment: Alignment.center, // 保证背景始终居中,不会偏移 ), ), ), ), // 页面内容层 Scaffold( backgroundColor: Colors.transparent, // resizeToAvoidBottomInset保持默认true即可,不需要手动设置为false body: SafeArea( child: SingleChildScrollView( // 这里放原来的页面内容,包含TextField child: ... ), ), ), ], ); } }
如果存在多个输入框,自动滚动位置不符合预期,可以额外给TextField绑定FocusNode,监听焦点变化,手动控制滚动偏移:
// 声明FocusNode final _textFieldFocus = FocusNode(); @override void initState() { super.initState(); _textFieldFocus.addListener(() { if (_textFieldFocus.hasFocus) { // 输入框获得焦点时,手动滚动到对应位置,偏移量可根据实际布局调整 Scrollable.ensureVisible( _textFieldFocus.context!, alignment: 0.5, // 滚动到屏幕中间位置 duration: const Duration(milliseconds: 200), ); } }); } // TextField绑定focusNode TextField( focusNode: _textFieldFocus, ... ) @override void dispose() { _textFieldFocus.dispose(); super.dispose(); }
内容的提问来源于stack exchange,提问作者Sam Doggett
相关产品推荐
相关产品推荐

