You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

移动端Match Lobbies筛选功能软键盘弹出时底部溢出121像素求助

解决Flutter BottomSheet键盘弹出底部溢出问题

问题原因

  • 你给BottomSheet内部的SizedBox设置了固定高度595.h,当软键盘弹出时,屏幕可用垂直空间被压缩,固定高度超过剩余空间导致溢出。
  • 内容Column没有包裹在可滚动组件中,无法在空间不足时滚动适配。

修复方案

  1. 移除固定高度的SizedBox,改用SingleChildScrollView包裹Column,让内容可以滚动适配高度变化。
  2. 启用BottomSheet的isScrollControlled属性,允许BottomSheet根据屏幕可用高度调整自身尺寸,配合MediaQuery.viewInsets处理键盘高度。
  3. 保留底部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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 15:30:50