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

Flutter中如何让showModalBottomSheet内的Form不被软键盘遮挡可滚动

问题解决方法

这个问题是showModalBottomSheet默认配置不支持软键盘适配导致的,只需要修改两处核心配置即可解决:

1. 调整showModalBottomSheet基础参数

添加两个核心参数:

  • isScrollControlled: true:允许底部弹窗高度自适应,跟随软键盘上浮
  • useSafeArea: true:避免弹窗内容超出系统顶部安全区域

2. 给弹窗根组件添加软键盘适配边距

在builder返回的组件外层套Padding,底部边距取当前软键盘的高度MediaQuery.of(context).viewInsets.bottom,确保内容整体顶在软键盘上方。同时给Column设置mainAxisSize: MainAxisSize.min,让弹窗只占用表单需要的最小高度。

修改后完整代码

import 'package:flutter/material.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

class UserScreen extends StatefulWidget {
  UserScreen({Key? key}) : super(key: key);

  @override
  _UserScreenState createState() => _UserScreenState();
}

class _UserScreenState extends State<UserScreen> {
  void addNewProducts(BuildContext ctx) {
    showModalBottomSheet(
      context: ctx,
      // 新增两个适配参数
      isScrollControlled: true,
      useSafeArea: true,
      builder: (_) {
        return GestureDetector(
          onTap: () {},
          behavior: HitTestBehavior.opaque,
          // 新增Padding适配软键盘高度
          child: Padding(
            padding: EdgeInsets.only(
              bottom: MediaQuery.of(ctx).viewInsets.bottom,
            ),
            child: Card(
              child: SingleChildScrollView(
                child: Form(
                  child: Column(
                    // 适配最小高度
                    mainAxisSize: MainAxisSize.min,
                    children: <Widget>[
                      const SizedBox(height: 20,),
                      TextFormField(
                        keyboardType: TextInputType.emailAddress,
                        decoration: const InputDecoration(
                            labelText: 'Product Name',
                            icon: Icon(Icons.insert_chart)),
                      ),
                      TextFormField(
                        keyboardType: TextInputType.emailAddress,
                        decoration: const InputDecoration(
                            labelText: 'Product Description',
                            icon: Icon(Icons.description)),
                      ),
                      TextFormField(
                        keyboardType: TextInputType.emailAddress,
                        decoration: const InputDecoration(
                            labelText: 'Minimum Bid Price',
                            icon: Icon(Icons.price_check)),
                      ),
                      TextFormField(
                        keyboardType: TextInputType.emailAddress,
                        decoration: const InputDecoration(
                            labelText: 'Auction End DateTime',
                            icon: Icon(Icons.data_saver_off)),
                      ),
                      const SizedBox(
                        height: 20,
                      ),
                      ElevatedButton(
                        onPressed: () {},
                        child: const Text('Add Product'),
                      ),
                      const SizedBox(height: 20,),
                    ],
                  ),
                ),
              ),
            ),
          ),
        );
      },
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('User Screen'),
        actions: [
          DropdownButton(
            items: [
              DropdownMenuItem(
                value: 'logout',
                child: Row(
                  children: <Widget>[
                    Icon(
                      Icons.exit_to_app,
                      color: Theme.of(context).indicatorColor,
                    ),
                    const SizedBox(
                      width: 8,
                    ),
                    const Text('Logout')
                  ],
                ),
              ),
            ],
            onChanged: (itemIdentifire) {
              if (itemIdentifire == 'logout') {
                FirebaseAuth.instance.signOut();
              }
            },
          )
        ],
      ),
      body: const Card(),
      floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
      floatingActionButton: FloatingActionButton(
        child: const Icon(Icons.add),
        onPressed: () {
          addNewProducts(context);
        },
      ),
    );
  }
}

问题场景参考截图

  • 点击按钮唤起的初始表单界面:
    点击floatingActionButton弹出的表单,点击TextFormField输入时软键盘会遮挡整个区域
  • 原问题唤起软键盘后的遮挡效果:
    点击TextFormField准备输入时,软键盘完全遮盖整个表单

修改完成后点击输入框时,弹窗会自动整体上浮到软键盘上方,内部表单支持滚动,不会再出现遮挡问题。

内容的提问来源于stack exchange,提问作者Md. Fazle Rabbi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 19:39:02