Compose ExposedDropdownMenu在Edge-to-Edge模式下的系统栏显示问题
问题根源
ExposedDropdownMenu的PopupWindow在显示时,默认会触发系统栏Insets的重新计算,导致Edge-to-Edge模式下隐藏的导航栏被自动唤起,进而改变页面布局高度,引发菜单位置计算异常(如向上弹出、卡顿)。
解决方案
通过监听下拉菜单的展开/收起事件,手动控制其PopupWindow的系统栏行为,强制保持导航栏隐藏:
单个菜单处理示例
// 假设你的下拉菜单为MaterialAutoCompleteTextView实例 val dropdownMenu = binding.yourDropdownMenuId dropdownMenu.setOnExpandListener(object : ExposedDropdownMenu.OnExpandListener { override fun onExpand(isExpanded: Boolean) { dropdownMenu.popupWindow?.let { popupWindow -> val activity = popupWindow.contentView.context as? Activity ?: return@let val insetsController = WindowInsetsControllerCompat(activity.window, popupWindow.contentView) if (isExpanded) { // 展开时强制隐藏导航栏,并设置仅通过滑动唤起导航栏 insetsController.hide(WindowInsetsCompat.Type.systemBars()) insetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE // 确保PopupWindow独占触摸事件,避免触发系统栏 popupWindow.setTouchModal(true) // 设置布局类型,避免触发系统栏Insets重计算 PopupWindowCompat.setWindowLayoutType(popupWindow, WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL) } else { // 收起菜单后恢复原有系统栏行为 insetsController.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE } } } })
多菜单统一处理
如果存在多个ExposedDropdownMenu,可以封装工具方法批量配置:
fun setupDropdownSystemBarBehavior(dropdown: MaterialAutoCompleteTextView) { dropdown.setOnExpandListener(object : ExposedDropdownMenu.OnExpandListener { override fun onExpand(isExpanded: Boolean) { dropdown.popupWindow?.let { popup -> val activity = popup.contentView.context as? Activity ?: return val controller = WindowInsetsControllerCompat(activity.window, popup.contentView) if (isExpanded) { controller.hide(WindowInsetsCompat.Type.systemBars()) controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_BARS_BY_SWIPE popup.setTouchModal(true) PopupWindowCompat.setWindowLayoutType(popup, WindowManager.LayoutParams.TYPE_APPLICATION_SUB_PANEL) } else { controller.systemBarsBehavior = WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE } } } }) } // 使用方式 setupDropdownSystemBarBehavior(binding.dropdownMenu1) setupDropdownSystemBarBehavior(binding.dropdownMenu2)
关键说明
setTouchModal(true):让PopupWindow消费所有触摸事件,防止事件透传到底层触发系统栏显示TYPE_APPLICATION_SUB_PANEL:指定PopupWindow的布局类型,避免触发系统栏Insets的重新计算- 切换系统栏行为:展开时改为仅通过滑动唤起导航栏,收起后恢复原有的"短暂显示"行为,保留原有交互逻辑
内容的提问来源于stack exchange,提问作者Ivan Beskorovayniy
相关产品推荐
相关产品推荐

