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

Flutter中showModalBottomSheet弹出TextFormField时底部溢出问题求助

Flutter showModalBottomSheet 底部溢出及内容消失问题解决

问题描述

使用showModalBottomSheet实现评论输入弹窗时,点击TextFormField唤起键盘后出现底部溢出。尝试以下两种方案均无效:

  • 用SingleChildScrollView包裹最外层Column:模态框直接被隐藏
  • 用ListView包裹最外层Column:弹窗内所有内容消失,仅显示空白面板

原代码

showModalBottomSheet(
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(15.0),
    ),
    context: context,
    builder: (context) {
      return Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          children: [
            Expanded(
              child: Column(
                children: [
                  Row(
                    children: [
                      CircleAvatar(
                        radius: 22,
                        backgroundImage: NetworkImage(
                            '${SocialCubit.get(context).userModel!.image}'),
                      ),
                      SizedBox(
                        width: 15,
                      ),
                      Container(
                        decoration: BoxDecoration(
                          borderRadius:
                              BorderRadius.circular(10),
                          color: Colors.grey[350],
                        ),
                        child: Padding(
                          padding:
                              const EdgeInsets.all(8.0),
                          child: Column(
                            crossAxisAlignment:
                                CrossAxisAlignment.start,
                            children: [
                              Row(
                                children: [
                                  Text(
                                    '${SocialCubit.get(context).userModel!.name}',
                                    style: TextStyle(
                                        fontSize: 15,
                                        fontWeight:
                                            FontWeight
                                                .bold),
                                  ),
                                  SizedBox(
                                    width: 7,
                                  ),
                                  Text(
                                    '2 minutes ago',
                                    style: TextStyle(
                                        fontSize: 11),
                                  ),
                                ],
                              ),
                              SizedBox(
                                height: 5,
                              ),
                              Text(
                                  'whats up broo i need to ask you something'),
                            ],
                          ),
                        ),
                      ),
                    ],
                  ),
                  if (model.postImage != '')
                    Padding(
                      padding: const EdgeInsetsDirectional.only(top: 15,start: 67),
                      child: Container(
                          height: 140,
                          width: double.infinity,
                          decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(4),
                            image: DecorationImage(
                              image: NetworkImage('${model.postImage}'),
                              fit: BoxFit.cover,
                            ),
                          )),
                    ),
                ],
              ),
            ),
            Padding(
              padding: EdgeInsets.only(
                  bottom: MediaQuery.of(context)
                      .viewInsets
                      .bottom),
              child: Row(
                children: [
                  CircleAvatar(
                    radius: 18,
                    backgroundImage: NetworkImage(
                        '${SocialCubit.get(context).userModel!.image}'),
                  ),
                  SizedBox(
                    width: 15,
                  ),
                  Expanded(
                    child: Container(
                      decoration: BoxDecoration(
                        borderRadius:
                            BorderRadius.circular(30),
                        color: Colors.grey[300],
                      ),
                      child: Padding(
                        padding: const EdgeInsets.symmetric(horizontal: 20),
                        child: TextFormField(
                          decoration: InputDecoration(
                            border: InputBorder.none,
                            hintText: 'Write your comment ...'
                          ),
                        ),

                      ),
                    ),
                  ),
                  IconButton(
                      onPressed: () {},
                      icon: Icon(IconBroken.Send)),
                ],
              ),
            ),
          ],
        ),
      );
    });

尝试后的现象

  • 溢出问题:唤起键盘后,弹窗底部被截断,出现底部溢出提示
  • ListView包裹后:弹窗内无任何内容,仅显示空白面板
  • SingleChildScrollView包裹后:整个模态框被隐藏,无法看到任何内容

解决方案

核心修改点

  1. 给showModalBottomSheet添加isScrollControlled: true,让弹窗可以自适应键盘高度
  2. 用SingleChildScrollView包裹最外层内容,移除不必要的Expanded(SingleChildScrollView不需要子组件占满剩余空间)
  3. 给Column添加mainAxisSize: MainAxisSize.min,让Column仅占用内容所需高度

修改后的代码

showModalBottomSheet(
    isScrollControlled: true, // 允许弹窗自适应键盘高度
    shape: RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(15.0),
    ),
    context: context,
    builder: (context) {
      return SingleChildScrollView(
        padding: EdgeInsets.only(
          bottom: MediaQuery.of(context).viewInsets.bottom,
          left: 20,
          right: 20,
          top: 20,
        ),
        child: Column(
          mainAxisSize: MainAxisSize.min, // 让Column仅包裹内容高度
          children: [
            // 移除外层Expanded,直接保留内容Column
            Column(
              children: [
                Row(
                  children: [
                    CircleAvatar(
                      radius: 22,
                      backgroundImage: NetworkImage(
                          '${SocialCubit.get(context).userModel!.image}'),
                    ),
                    SizedBox(
                      width: 15,
                    ),
                    Container(
                      decoration: BoxDecoration(
                        borderRadius:
                            BorderRadius.circular(10),
                        color: Colors.grey[350],
                      ),
                      child: Padding(
                        padding:
                            const EdgeInsets.all(8.0),
                        child: Column(
                          crossAxisAlignment:
                              CrossAxisAlignment.start,
                          children: [
                            Row(
                              children: [
                                Text(
                                  '${SocialCubit.get(context).userModel!.name}',
                                  style: TextStyle(
                                      fontSize: 15,
                                      fontWeight:
                                          FontWeight
                                              .bold),
                                ),
                                SizedBox(
                                  width: 7,
                                ),
                                Text(
                                  '2 minutes ago',
                                  style: TextStyle(
                                      fontSize: 11),
                                ),
                              ],
                            ),
                            SizedBox(
                              height: 5,
                            ),
                            Text(
                                'whats up broo i need to ask you something'),
                          ],
                        ),
                      ),
                    ),
                  ],
                ),
                if (model.postImage != '')
                  Padding(
                    padding: const EdgeInsetsDirectional.only(top: 15,start: 67),
                    child: Container(
                        height: 140,
                        width: double.infinity,
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(4),
                          image: DecorationImage(
                            image: NetworkImage('${model.postImage}'),
                            fit: BoxFit.cover,
                          ),
                        )),
                  ),
              ],
            ),
            SizedBox(height: 20), // 分隔内容和输入栏的间距
            Row(
              children: [
                CircleAvatar(
                  radius: 18,
                  backgroundImage: NetworkImage(
                      '${SocialCubit.get(context).userModel!.image}'),
                ),
                SizedBox(
                  width: 15,
                ),
                Expanded(
                  child: Container(
                    decoration: BoxDecoration(
                      borderRadius:
                          BorderRadius.circular(30),
                      color: Colors.grey[300],
                    ),
                    child: Padding(
                      padding: const EdgeInsets.symmetric(horizontal: 20),
                      child: TextFormField(
                        decoration: InputDecoration(
                          border: InputBorder.none,
                          hintText: 'Write your comment ...'
                        ),
                      ),
                    ),
                  ),
                ),
                IconButton(
                    onPressed: () {},
                    icon: Icon(IconBroken.Send)),
              ],
            ),
          ],
        ),
      );
    });

原理说明

  • isScrollControlled: true:让弹窗高度可超过屏幕一半,自动调整高度避免被键盘遮挡
  • SingleChildScrollView:确保内容过多或键盘弹出时可滚动,解决溢出问题
  • mainAxisSize: MainAxisSize.min:避免Column不必要的拉伸,防止布局异常导致内容隐藏

内容的提问来源于stack exchange,提问作者hazem saad

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 11:00:59