Flutter键盘遮挡底部输入框问题求助
解决Flutter键盘遮挡输入框且ListView滚动后自动回滚的问题
问题原因
你当前使用shrinkWrap: true的ListView会让列表高度完全适配内容,当键盘弹出时页面布局重排,导致滚动位置自动重置;同时未处理键盘弹出时的底部间距,最终引发输入框被遮挡的问题。
解决方案
推荐替换ListView为SingleChildScrollView + Column的组合,配合MediaQuery添加键盘弹出时的动态底部padding,这是处理此类场景最稳定的方案:
return SingleChildScrollView( keyboardDismissBehavior: ScrollViewKeyboardDismissBehavior.manual, // 动态添加底部padding,避免键盘遮挡输入框 padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), child: Column( mainAxisSize: MainAxisSize.min, children: [ SizedBox( width: 100, height: 100, child: Image.network(state.specificPaymentTypeModels.icon), ), Container( margin: const EdgeInsets.symmetric(horizontal: 10, vertical: 10), child: Text( state.specificPaymentTypeModels.title, textAlign: TextAlign.center, ), ), SizedBox( width: width / 1.5, child: Html( data: state.specificPaymentTypeModels.description, )), state.specificPaymentTypeModels.alias == 'freedom-pay' || state.specificPaymentTypeModels.alias == 'balancekg' || state.specificPaymentTypeModels.alias == 'megapay' || state.specificPaymentTypeModels.alias == 'odengi' ? Container( margin: EdgeInsets.only(top: 15), child: MyTextField( hint: 'Введите сумму пополнения', myController: summa, )) : Container(), state.specificPaymentTypeModels.alias == 'megapay' || state.specificPaymentTypeModels.alias == 'balancekg' ? Container( margin: const EdgeInsets.fromLTRB(16, 10, 16, 0), decoration: BoxDecoration( border: Border( top: BorderSide( color: ConfigColor.lightGrey, width: 1.5), bottom: BorderSide( color: ConfigColor.lightGrey, width: 1.5), right: BorderSide( color: ConfigColor.lightGrey, width: 1.5), left: BorderSide( color: ConfigColor.lightGrey, width: 1.5)), color: Colors.white, ), child: TextField( controller: number, inputFormatters: [maskFormatter], style: TextStyle( color: ConfigColor.textBlack, fontWeight: FontWeight.w400, ), decoration: InputDecoration( hintText: '996 (707)-098-995', hintStyle: TextStyle( fontSize: 16, color: Colors.grey, fontWeight: FontWeight.w400, ), fillColor: Colors.white, filled: true, border: OutlineInputBorder( borderRadius: BorderRadius.circular(4), borderSide: BorderSide.none)), )) : Container(), state.specificPaymentTypeModels.alias == 'freedom-pay' || state.specificPaymentTypeModels.alias == 'balancekg' || state.specificPaymentTypeModels.alias == 'megapay' || state.specificPaymentTypeModels.alias == 'odengi' ? InkWell( onTap: () async { await context.read<ReciveTypeCubit>() ..reciveType( number.text == null ? '123456789123' : '996${maskFormatter.getUnmaskedText()}', state.specificPaymentTypeModels.alias, int.parse(summa.text)) .whenComplete(() async { context.go('/reciveType'); final prefs = await SharedPreferences.getInstance(); await prefs.setString('phoneNumberPayments', '996${maskFormatter.getUnmaskedText()}'); print(await prefs.getString('phoneNumberPayments')); }); }, child: Container( width: double.infinity, margin: EdgeInsets.only(top: 15), padding: const EdgeInsets.symmetric(vertical: 12), decoration: BoxDecoration( color: ConfigColor.green, borderRadius: BorderRadius.circular(32)), child: Text( 'Готово', textAlign: TextAlign.center, style: TextStyle( color: Colors.white, fontWeight: FontWeight.w500, fontSize: 16), ), ), ) : Container() ], ), );
额外说明
如果一定要保留ListView,需要做两个关键修改:
- 移除
shrinkWrap: true,并用Expanded包裹ListView,给它一个确定的父布局高度 - 添加底部动态padding:
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom)
这样能避免滚动后自动回滚的问题,同时确保输入框不被键盘遮挡。
内容的提问来源于stack exchange,提问作者Daniil
相关产品推荐
相关产品推荐

