Flutter Bottom Sheet添加Form Key后键盘弹出即消失问题
问题:BottomSheet中Form绑定GlobalKey后,TextFormField弹出键盘立即消失
在Flutter项目中使用Bottom Sheet承载表单,为Form组件设置GlobalKey
控制台输出日志:
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变量与成员变量重名,存在变量遮蔽问题,建议改名避免混淆。
修改步骤:
- 将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, ), ], ), ); } }
- 额外优化:
- 将build方法中的
width/height改为screenWidth/screenHeight,避免遮蔽成员变量; - 给TextFormField添加const修饰(无动态变化需求时),提升页面性能。
修改后,Form状态由State类持有,键盘弹出时的布局变化不会导致状态丢失,输入框可正常保持焦点,键盘不会自动收起。
内容的提问来源于stack exchange,提问作者Shuhaib
相关产品推荐
相关产品推荐

