移动端Match Lobbies筛选功能软键盘弹出时底部溢出121像素求助
解决Flutter BottomSheet键盘弹出底部溢出问题
问题原因
- 你给BottomSheet内部的SizedBox设置了固定高度
595.h,当软键盘弹出时,屏幕可用垂直空间被压缩,固定高度超过剩余空间导致溢出。 - 内容Column没有包裹在可滚动组件中,无法在空间不足时滚动适配。
修复方案
- 移除固定高度的SizedBox,改用
SingleChildScrollView包裹Column,让内容可以滚动适配高度变化。 - 启用BottomSheet的
isScrollControlled属性,允许BottomSheet根据屏幕可用高度调整自身尺寸,配合MediaQuery.viewInsets处理键盘高度。 - 保留底部padding以避开键盘区域,确保输入框不会被键盘遮挡。
修改后的完整代码
Widget build(BuildContext context) { return Padding( padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), child: BottomSheet( onClosing: () => {}, // 启用滚动控制,让BottomSheet适配可用高度 isScrollControlled: true, builder: (_) { return SingleChildScrollView( child: Padding( padding: EdgeInsets.symmetric(horizontal: 15.w), child: Column( // 让Column只占用内容所需高度 mainAxisSize: MainAxisSize.min, children: [ Align( alignment: Alignment.centerLeft, child: Container( padding: EdgeInsets.only( top: 34.h, left: 40.w, ), child: Text( 'Filter', style: Theme.of(context).textTheme.titleMedium?.copyWith( fontSize: 28.sp, fontWeight: FontWeight.w600, ), ), ), ), Container( decoration: BoxDecoration( color: const Color(0xFF2B2B3D), borderRadius: BorderRadius.circular( 10.r, ), ), child: CustomTextField( hintText: 'Host Username', controller: _controller, onChanged: (p0) => print(p0), ), ), SizedBox( height: 12.h, ), Container( height: 150.h, decoration: BoxDecoration( color: const Color(0xFF2B2B3D), borderRadius: BorderRadius.circular( 10.r, ), ), child: Column( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ Expanded( child: ListView( scrollDirection: Axis.horizontal, children: [ SizedBox( width: 200.w, child: RadioListTile<String>( activeColor: Colors.white, title: Text( "By Team", style: Theme.of(context).textTheme.bodyMedium, ), value: "team", groupValue: selectedMatchFilter, onChanged: (String? value) => setState(() { selectedMatchFilter = value; }), ), ), SizedBox( width: 200.w, child: RadioListTile<String>( activeColor: Colors.white, title: Text( "By League", style: Theme.of(context).textTheme.bodyMedium, ), value: "league", groupValue: selectedMatchFilter, onChanged: (String? value) => setState(() { selectedMatchFilter = value; }), ), ), ], ), ), SizedBox( height: 100.h, child: Row( children: [ Expanded( child: ListView.builder( itemCount: 10, scrollDirection: Axis.horizontal, itemBuilder: (context, index) => SizedBox( height: 100.h, width: 125.w, child: TeamLogo( id: 1, imgPath: "Barcelona", teamName: "Barcelona", selected: false, notifyParent: () {}, ), ), ), ), ], ), ), ], ), ), Container( padding: EdgeInsets.only(top: 5.h), child: const Text( "Matchday", textAlign: TextAlign.center, ), ), Column( children: [ RadioListTile<DateTime>( activeColor: Colors.white, title: Text( "Today", style: Theme.of(context).textTheme.bodyMedium, ), value: widget.today, groupValue: selectedMatchDateFilter, onChanged: (DateTime? value) => setState(() { selectedMatchDateFilter = value; }), ), RadioListTile<DateTime>( activeColor: Colors.white, title: Text( "Tomorrow", style: Theme.of(context).textTheme.bodyMedium, ), value: DateTime(DateTime.now().year, DateTime.now().month, DateTime.now().day + 1), groupValue: selectedMatchDateFilter, onChanged: (DateTime? value) => setState(() { selectedMatchDateFilter = value; }), ), RadioListTile<DateTime>( activeColor: Colors.white, title: Row( children: [ DropdownButton2<String>( isExpanded: true, buttonHeight: 30.h, buttonWidth: 220.w, items: const [ DropdownMenuItem<String>( value: "", child: Text("Till Date"), ), DropdownMenuItem<String>( value: "", child: Text("Precise Date"), ), ], ), 1 == 2 ? Checkbox( value: true, onChanged: (bool? _value) {}, ) : IconButton( icon: const Icon(Icons.calendar_today), onPressed: () => showDatePicker( context: context, initialDate: DateTime.now(), firstDate: DateTime(2022, 11, 16), lastDate: DateTime(2023, 1, 1), ), ), ], ), value: DateTime.now(), groupValue: selectedMatchDateFilter, onChanged: (value) {}, ) ], ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text("Premium"), Switch( onChanged: (bool? s) => setState(() { isPremiumFilter = s ?? false; }), value: isPremiumFilter, activeColor: const Color(0xFF182A54), inactiveThumbColor: Colors.white, activeTrackColor: const Color(0xFFD9D9D9), inactiveTrackColor: const Color(0xFFD9D9D9), ), ], ), SizedBox(height: 20.h), // 增加底部间距避免按钮贴边 Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ TextButton( onPressed: () {}, child: const Text("Apply"), ), TextButton( onPressed: () {}, child: const Text("Clear All"), ), ], ), ], ), ), ); }, ), ); }
关键改动说明
- 添加
isScrollControlled: true:让BottomSheet可以占据屏幕剩余可用高度,而非固定高度。 - 替换
SizedBox为SingleChildScrollView:允许内容在空间不足时垂直滚动,避免溢出。 - 设置
Column(mainAxisSize: MainAxisSize.min):让Column仅包裹内容所需高度,而非强制扩展。 - 增加底部间距:避免底部按钮被键盘或屏幕边缘遮挡。
内容的提问来源于stack exchange,提问作者Chaitya Vohera
相关产品推荐
相关产品推荐

