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

Flutter Bottom Sheet添加Form Key后键盘弹出即消失问题

问题:BottomSheet中Form绑定GlobalKey后,TextFormField弹出键盘立即消失

在Flutter项目中使用Bottom Sheet承载表单,为Form组件设置GlobalKey后,点击TextFormField时键盘弹出后迅速消失。

控制台输出日志:

app_time_stats: avg=1118.30ms min=24.14ms max=3052.74ms count=3
D/InputMethodManager(11721): showSoftInput() view=io.flutter.embedding.android.FlutterView{f865cd3 VFE...... .F...... 0,0-1080,2148 #1 aid=1073741824} flags=0 reason=SHOW_SOFT_INPUT
D/InputConnectionAdaptor(11721): The input method toggled cursor monitoring on
D/InsetsController(11721): show(ime(), fromIme=true)
D/EGL_emulation(11721): app_time_stats: avg=240.46ms min=14.44ms max=1273.18ms count=7
D/EGL_emulation(11721): app_time_stats: avg=3881.66ms min=1.37ms max=127754.21ms count=33
D/InputConnectionAdaptor(11721): The input method toggled cursor monitoring off

相关代码实现:

class ProductModelBottomSheet extends StatelessWidget {
  ProductModelBottomSheet({
    super.key,
    required this.height,
    required this.width,
    this.productID = 0,
    this.productName = '',
    this.productCode = '',
    this.productUOM = '',
    this.productPrice = 0,
    required this.isUpdate,
  });
  final double height;
  final double width;
  final String productName;
  final String productCode;
  final String productUOM;
  final double productPrice;
  final int productID;
  final bool isUpdate;
  final productFormKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    final width = MediaQuery.of(context).size.width;
    final height = MediaQuery.of(context).size.height;

    return Container(
      height: height * .8,
      decoration: const BoxDecoration(
          ),
      width: width,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                isUpdate == false
                    ? "  Enter item details"
                    : "  Update item details",
                style: const TextStyle(
                  fontWeight: FontWeight.w600,
                  fontSize: 16,
                ),
              ),
              IconButton(
                onPressed: () {},
                icon: const Icon(
                  Icons.info,
                ),
              ),
            ],
          ),
          Form(
            key: productFormKey,
            child: SingleChildScrollView(
              child: Column(
                children: [TextFormField()],
              ),
            ),
          ),
          SizedBox(
            height: height * .07,
            width: width,
          ),

         
        ],
      ),
    );
  }
}

解决方案

核心问题在于GlobalKey的存储位置和Widget类型不匹配:

  • 你将productFormKey定义在StatelessWidget成员中,当键盘弹出触发BottomSheet重新布局时,StatelessWidget会被重建,Form的关联状态丢失,导致输入框失去焦点,键盘自动收起。
  • 另外,build方法内的width/height变量与成员变量重名,存在变量遮蔽问题,建议改名避免混淆。

修改步骤:

  1. 将StatelessWidget改为StatefulWidget,把productFormKey移到State类中,确保Form状态在布局变化时不会丢失:
class ProductModelBottomSheet extends StatefulWidget {
  const ProductModelBottomSheet({
    super.key,
    required this.height,
    required this.width,
    this.productID = 0,
    this.productName = '',
    this.productCode = '',
    this.productUOM = '',
    this.productPrice = 0,
    required this.isUpdate,
  });

  final double height;
  final double width;
  final String productName;
  final String productCode;
  final String productUOM;
  final double productPrice;
  final int productID;
  final bool isUpdate;

  @override
  State<ProductModelBottomSheet> createState() => _ProductModelBottomSheetState();
}

class _ProductModelBottomSheetState extends State<ProductModelBottomSheet> {
  final productFormKey = GlobalKey<FormState>();

  @override
  Widget build(BuildContext context) {
    final screenWidth = MediaQuery.of(context).size.width;
    final screenHeight = MediaQuery.of(context).size.height;

    return Container(
      height: screenHeight * .8,
      decoration: const BoxDecoration(),
      width: screenWidth,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Row(
            mainAxisSize: MainAxisSize.max,
            mainAxisAlignment: MainAxisAlignment.spaceBetween,
            children: [
              Text(
                widget.isUpdate == false
                    ? "  Enter item details"
                    : "  Update item details",
                style: const TextStyle(
                  fontWeight: FontWeight.w600,
                  fontSize: 16,
                ),
              ),
              IconButton(
                onPressed: () {},
                icon: const Icon(Icons.info),
              ),
            ],
          ),
          Form(
            key: productFormKey,
            child: SingleChildScrollView(
              child: Column(
                children: const [TextFormField()],
              ),
            ),
          ),
          SizedBox(
            height: screenHeight * .07,
            width: screenWidth,
          ),
        ],
      ),
    );
  }
}
  1. 额外优化:
  • 将build方法中的width/height改为screenWidth/screenHeight,避免遮蔽成员变量;
  • 给TextFormField添加const修饰(无动态变化需求时),提升页面性能。

修改后,Form状态由State类持有,键盘弹出时的布局变化不会导致状态丢失,输入框可正常保持焦点,键盘不会自动收起。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 19:58:10