Flutter:键盘弹出时如何上移Overlay Widget?
解决键盘遮挡custom_pointed_popup弹窗的问题
问题原因
键盘遮挡弹窗的核心原因有两点:
- 创建弹窗时使用的
MediaQuery.viewInsetsOf(context)是静态值,键盘弹出后不会自动更新,无法动态适配键盘高度。 - Scaffold设置了
resizeToAvoidBottomInset: false,页面整体不会为键盘留出空间,弹窗位置也无法自动调整。
解决方案
以下是修改后的完整代码,可解决键盘遮挡问题:
import 'package:custom_pointed_popup/custom_pointed_popup.dart'; import 'package:custom_pointed_popup/utils/triangle_painter.dart'; import 'package:flutter/material.dart'; class HomeScreen extends StatefulWidget { const HomeScreen({super.key}); @override State<HomeScreen> createState() => _HomeScreenState(); } class _HomeScreenState extends State<HomeScreen> { List<GlobalKey> keys = List.generate(25, (index) => GlobalKey()); void show(GlobalKey key) { CustomPointedPopup popup = CustomPointedPopup( backgroundColor: Colors.grey.withOpacity(0.1), context: context, widthFractionWithRespectToDeviceWidth: 5, displayBelowWidget: true, triangleDirection: TriangleDirection.Straight, popupElevation: 10, item: CustomPointedPopupItem( // 使用Builder获取弹窗上下文,确保拿到实时的键盘偏移数据 itemWidget: Builder( builder: (popupContext) { return SingleChildScrollView( child: Padding( // 用弹窗上下文获取键盘弹出后的实时viewInsets padding: MediaQuery.of(popupContext).viewInsets, child: Column( mainAxisSize: MainAxisSize.min, children: [ for (int i = 0; i < 5; i++) const Text('hello'), TextField( scrollPadding: EdgeInsets.zero, ) ], ), ), ); }, ), ), onClickWidget: (onClickMenu) { print('popup item clicked'); print(onClickMenu); }, onDismiss: () { print('on dismissed called'); }, ); popup.show(widgetKey: key); } @override Widget build(BuildContext context) { return Scaffold( body: GridView.builder( gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 4, mainAxisSpacing: 32, crossAxisSpacing: 32, mainAxisExtent: 120, ), itemBuilder: (_, int pos) { return InkWell( onTap: () { show(keys[pos]); }, child: Container( key: keys[pos], color: pos % 2 == 0 ? Colors.black : Colors.grey, ), ); }, itemCount: keys.length, ), // 移除该属性,让Scaffold自动为键盘调整布局;若业务必须保留,需额外监听键盘事件手动调整弹窗位置 // resizeToAvoidBottomInset: false, ); } }
关键修改说明
- 移除
resizeToAvoidBottomInset: false:让Scaffold自动响应键盘弹出事件,页面整体布局会向上偏移,带动弹窗位置适配。若业务必须保留该属性,可通过WidgetsBinding.instance.addObserver监听键盘高度变化,手动调整弹窗位置。 - 使用
Builder获取弹窗上下文:确保能获取到键盘弹出后的实时MediaQuery.viewInsets,替代创建弹窗时的静态值。 - 添加
SingleChildScrollView包裹弹窗内容:当键盘弹出后,弹窗内容可滚动,避免TextField被遮挡。 - 调整
TextField的scrollPadding:设置为EdgeInsets.zero,配合外部的Padding确保滚动位置准确。
内容的提问来源于stack exchange,提问作者Balaji
相关产品推荐
相关产品推荐

