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

Flutter:解决Bottom Sheet中输入框被键盘遮挡的问题

解决Bottom Sheet中评论输入框被键盘遮挡的问题

核心问题分析

  1. showModalBottomSheet默认未开启键盘适配,需启用滚动控制让Bottom Sheet响应键盘高度变化
  2. viewInsets内边距添加层级错误,应作用在Bottom Sheet根容器,而非输入框父级组件
  3. 固定Bottom Sheet高度导致无法自适应键盘弹出后的布局调整

修改步骤及代码

1. 调整showModalBottomSheet配置

添加isScrollControlled: true开启键盘适配:

showModalBottomSheet(
  useRootNavigator: true,
  isScrollControlled: true, // 关键:开启滚动控制,让Bottom Sheet适配键盘高度
  shape: const RoundedRectangleBorder(
    borderRadius: BorderRadius.vertical(
      top: Radius.circular(16),
    ),
  ),
  context: context,
  builder: (BuildContext context) {
    return CustomBottomSheetBuilder(
      tinggi: MediaQuery.of(context).size.height,
      isi: const [
        CommentContent(),
      ],
      header: true,
      judul: 'Comments',
    );
  });

2. 修改CustomBottomSheetBuilder布局

去掉固定高度,将viewInsets padding移到根容器,让Bottom Sheet自适应高度:

Container(
  constraints: BoxConstraints(
    maxHeight: MediaQuery.of(context).size.height - kBottomNavigationBarHeight,
  ),
  decoration: BoxDecoration(
    color: MyColor.white,
    borderRadius: const BorderRadius.only(
      topLeft: Radius.circular(25.0),
      topRight: Radius.circular(25.0),
    ),
  ),
  child: Padding(
    padding: MediaQuery.of(context).viewInsets, // 根容器添加viewInsets,避开键盘
    child: Column(
      mainAxisSize: MainAxisSize.min, // 让Column仅占用所需高度
      children: [
        widget.header == true
            ? Container(
                decoration: BoxDecoration(
                  border: Border(
                    bottom: BorderSide(
                      width: .5,
                      color: MyColor.neutralLow,
                    ),
                  ),
                ),
                height: 64,
                child: Padding(
                  padding: const EdgeInsets.symmetric(horizontal: 16),
                  child: Row(
                    crossAxisAlignment: CrossAxisAlignment.center,
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Text(
                        widget.judul == null ? '' : widget.judul!,
                        style: TextStyle(
                          fontSize: 16,
                          fontWeight: FontWeight.w500,
                          color: MyColor.neutralHigh,
                        ),
                      ),
                      TextActionButton(
                        teks: 'Cancel',
                        onPressed: () {
                          Navigator.pop(context);
                        },
                      ),
                    ],
                  ),
                ),
              )
            : const SizedBox(height: 48),
        Expanded(
          child: Padding(
            padding: const EdgeInsets.all(16),
            child: ListView(
              children: widget.isi,
            ),
          ),
        ),
      ],
    ),
  ),
);

3. 优化CommentContent布局

去掉输入框外层的Flexible和多余的viewInsets padding,简化布局:

ConstrainedBox(
  constraints: BoxConstraints(
    maxHeight: MediaQuery.of(context).size.height * 0.8,
  ),
  child: Column(
    mainAxisSize: MainAxisSize.min,
    children: [
      Flexible(
        child: ListView.builder(
          shrinkWrap: true,
          reverse: true,
          itemBuilder: ((context, index) {
            final Comment comments = commentList[index];
            return Card(
              shape: const RoundedRectangleBorder(
                borderRadius: BorderRadius.all(Radius.circular(3)),
              ),
              child: Padding(
                padding: const EdgeInsets.all(8.0),
                child: Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  children: [
                    Row(
                      children: [
                        CircleAvatar(
                          radius: 12,
                          child: Image.asset(comments.image),
                        ),
                        Padding(
                          padding: const EdgeInsets.only(left: 8),
                          child: Column(
                            crossAxisAlignment: CrossAxisAlignment.start,
                            children: [
                              Text(
                                comments.name,
                                style: const TextStyle(
                                  fontSize: 12,
                                  fontWeight: FontWeight.w500,
                                ),
                              ),
                              Text(
                                comments.day,
                                style: TextStyle(
                                  fontSize: 10,
                                  color: MyColor.neutralMediumLow,
                                ),
                              ),
                            ],
                          ),
                        ),
                        const Spacer(),
                        CustomPopupMenuButton(
                          itemBuilder: (context) => [
                            PopupMenuItem(
                              value: 1,
                              child: Row(
                                children: [
                                  Text(
                                    "Delete Comment",
                                    style: TextStyle(color: MyColor.danger),
                                  ),
                                ],
                              ),
                            ),
                          ],
                          onSelected: (value) {
                            if (value == 1) {}
                          },
                        ),
                      ],
                    ),
                    const SizedBox(height: 10),
                    Padding(
                      padding: const EdgeInsets.only(right: 8),
                      child: Text(comments.comment),
                    )
                  ],
                ),
              ),
            );
          }),
          itemCount: commentList.length,
        ),
      ),
      Padding(
        padding: const EdgeInsets.only(top: 8),
        child: TextBox(
          textEditingController: commentController,
          hintText: 'Type what are you thinking here ...',
          suffixIcon: IconButton(
            onPressed: () {},
            icon: const Icon(Icons.send),
          ),
        ),
      ),
    ],
  ),
);

修改说明

  • isScrollControlled: true:让Bottom Sheet可根据键盘高度动态调整自身高度,是解决键盘遮挡的核心开关
  • 根容器添加viewInsets padding:确保整个Bottom Sheet向上偏移避开键盘,而非仅调整输入框位置
  • 移除固定高度:避免布局被固定死,允许Bottom Sheet在键盘弹出时自适应缩小高度
  • 简化输入框布局:去掉不必要的Flexible,让输入框保持合适高度,避免布局冲突

内容的提问来源于stack exchange,提问作者Ardhya Chandra

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 19:07:07