PopupWindow的使用showAsDropDown()无法dismiss解决方法

本文介绍了在Android中使用PopupWindow的showAsDropDown方法时遇到无法dismiss的问题及解决办法。指出若PopupWindow未设置背景,则不会响应dismiss操作,这是一种已知的bug。通过调整代码顺序,先设置背景再调用showAsDropDown方法可以解决该问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

PopupWindow的使用showAsDropDown()无法dismiss解决方法


     Android PopupWindow的使用和分析,看这个连接;


在这篇文章的最后,博主给我们说了这个方法, showAsDropDown()显示在一个参照物View的周围,有三个方法重载:重点是我用了这个方法之后,弹出之后无法dismiss();后来博主又说popupWindow不设置背景是不会被dismiss()掉,这是一个bug。后来看了下代码,发现自己把showAsDropDown()方法写在设置背景的代码的上面了。

popupWindow.setBackgroundDrawable(getResources().getDrawable(
        R.drawable.home_pop_bg));//设置背景
// 设置好参数之后再show
popupWindow.showAsDropDown(mKefu,20,20);//设置距离某个控件位置
popupWindow.setTouchable(true);
popupWindow.setFocusable(true); //设置点击menu以外其他地方以及返回键退出
popupWindow.setOutsideTouchable(true);   //设置触摸外面时消失
改成这样就可以了。。。





<think>我们正在讨论Android中PopupWindow的两种显示方法showAsDropDown和showAtLocation。根据引用内容,我们可以总结如下: 1. **showAtLocation方法**: - 方法签名:`public void showAtLocation(View parent, int gravity, int x, int y)` - 参数说明: - `parent`:这个View用于获取WindowToken,实际上PopupWindow会附着在Activity的Window上,所以parent可以是Activity中的任意View(最终效果一样)。 - `gravity`:指定PopupWindow的对齐方式,例如`Gravity.TOP | Gravity.RIGHT`表示在屏幕右上角显示。默认是`Gravity.NO_GRAVITY`(相当于`Gravity.LEFT | Gravity.TOP`)。 - `x`和`y`:相对于gravity所确定位置的偏移量。例如,如果gravity是`Gravity.TOP`,那么y就是距离屏幕顶部的距离;如果gravity是`Gravity.BOTTOM`,那么y就是距离屏幕底部的距离。 - 特点:PopupWindow的位置是相对于整个Window(屏幕)的,可以通过gravity和x、y参数精确控制位置。如果弹出位置超出了Window的范围,系统会自动调整使其显示在Window内(引用[1])。 2. **showAsDropDown方法**: - 方法签名:`public void showAsDropDown(View anchor)`,还有重载方法可以指定偏移量和对齐方式。 - 参数说明: - `anchor`:PopupWindow会以这个View为锚点,显示在它的下方(默认)。 - 重载方法:`showAsDropDown(View anchor, int xoff, int yoff, int gravity)`可以指定相对于锚点的偏移量(xoff, yoff)和重力(gravity)。这里的gravity是相对于锚点的,例如`Gravity.START`、`Gravity.TOP`等。 - 特点:PopupWindow的位置是相对于锚点View的,默认显示在锚点View的正下方。可以通过偏移量调整位置,也可以通过gravity改变对齐方式(引用[1])。 ### 主要区别总结: | 方法 | 相对位置 | 参数特点 | 使用场景 | |--------------------|----------------|---------------------------------------------|----------------------------------| | `showAtLocation` | 相对于整个Window | 通过gravity指定屏幕位置,x、y为偏移量 | 需要在屏幕任意位置(如中央、角落)显示 | | `showAsDropDown` | 相对于锚点View | 默认在锚点下方,可通过偏移量和gravity微调位置 | 需要紧贴某个控件(如下拉菜单)显示 | ### 使用示例: #### 1. 使用`showAtLocation`在屏幕右上角显示PopupWindow ```java PopupWindow popupWindow = new PopupWindow(contentView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); popupWindow.showAtLocation(anchorView, Gravity.TOP | Gravity.RIGHT, 10, 10); // 距离屏幕右上角各10像素 ``` #### 2. 使用`showAsDropDown`在锚点View下方显示PopupWindow ```java PopupWindow popupWindow = new PopupWindow(contentView, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT); popupWindow.showAsDropDown(anchorView); // 默认在anchorView正下方 ``` #### 3. 使用`showAsDropDown`重载方法在锚点View上方显示(通过负偏移) ```java // 计算锚点View在屏幕的位置 int[] location = new int[2]; anchorView.getLocationOnScreen(location); int anchorTop = location[1]; // 计算PopupWindow高度(需要先测量) contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED); int popupHeight = contentView.getMeasuredHeight(); // 显示在锚点View上方 popupWindow.showAsDropDown(anchorView, 0, -anchorView.getHeight() - popupHeight); ``` 或者使用带gravity的重载(API 19以上): ```java if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { popupWindow.showAsDropDown(anchorView, 0, 0, Gravity.BOTTOM); } ``` ### 注意事项: - **测量问题**:在显示PopupWindow之前,最好先测量其内容视图,以便正确计算位置和尺寸。 - **动画效果**:可以通过`setAnimationStyle`方法设置弹出动画(引用[4]提供了位移动画的示例)。 - **焦点问题**:默认情况下,点击PopupWindow外部区域会消失,可以通过`setOutsideTouchable(false)`禁用此行为。 - **内存泄漏**:在Activity销毁前,确保调用`dismiss()`方法销毁PopupWindow。 ### 相关问题 §§ 相关问题 §§ 1. PopupWindow如何实现自定义动画效果? 2. 如何解决PopupWindow在Android 7.0以上系统显示位置错误的问题? 3. PopupWindow和Dialog有什么区别? 4. 如何让PopupWindow在指定位置显示并响应外部点击事件? 5. PopupWindow在屏幕旋转时如何保持位置? [^1]: [引用1] [^2]: [引用2] [^3]: [引用3] [^4]: [引用4]</think>### Android PopupWindowshowAsDropDown 与 showAtLocation 方法详解 #### 一、核心区别总结 | 特性 | `showAsDropDown()` | `showAtLocation()` | |---------------------|-------------------------------------|-------------------------------------| | **相对基准** | 锚点 View(如按钮) | 整个 Window(屏幕坐标系) | | **位置控制** | 基于锚点位置偏移 | 基于屏幕坐标系 + Gravity 定位 | | **默认显示位置** | 锚点下方 | 屏幕左上角 (0,0) | | **超出屏幕处理** | 自动调整到屏幕内 | 自动调整到屏幕内 | | **适用场景** | 下拉菜单、工具提示 | 全屏弹窗、自定义位置悬浮窗 | --- #### 二、方法详解与代码示例 ##### 1. `showAsDropDown()` - 相对锚点定位 ```java // 基本用法(显示在锚点正下方) popupWindow.showAsDropDown(anchorView); // 带偏移量用法(X/Y轴偏移) popupWindow.showAsDropDown(anchorView, xOffset, yOffset); // 高级用法(API 19+ 带Gravity) if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) { popupWindow.showAsDropDown( anchorView, xOffset, yOffset, Gravity.START | Gravity.TOP ); } ``` **特点**: - 默认显示在锚点 View 正下方 - 偏移量单位是像素(px) - Gravity 用于控制对齐方式(如`Gravity.TOP`使弹窗出现在锚点上方) ##### 2. `showAtLocation()` - 绝对屏幕定位 ```java // 显示在屏幕左上角 popupWindow.showAtLocation( parentView, Gravity.NO_GRAVITY, x, y ); // 显示在屏幕右上角(带边距) popupWindow.showAtLocation( parentView, Gravity.TOP | Gravity.RIGHT, 10, // 右边距10px 10 // 上边距10px ); // 屏幕居中显示 popupWindow.showAtLocation( parentView, Gravity.CENTER, 0, 0 ); ``` **参数解析**: - **parentView**:任意 View(仅用于获取 WindowToken) - **gravity**:定位基准(组合使用如 `Gravity.TOP|Gravity.CENTER_HORIZONTAL`) - **x/y**:相对 gravity 的偏移量(单位 px) --- #### 三、关键差异图示 ``` 屏幕坐标系 (0,0) ┌───────────────────────────────────┐ │ showAtLocation() │ │ ▲ │ │ │ (x,y) │ │ └──┐ │ │ ┌───────────┐ │ │ │ │ ANCHOR │ │ PopupWindow │ │ │ VIEW │◄──┘ │ │ └───────────┘ │ │ │ │ showAsDropDown() ▼ │ │ PopupWindow │ └───────────────────────────────────┘ ``` --- #### 四、使用场景推荐 1. **推荐 `showAsDropDown()` 的情况**: - 下拉菜单(如Spinner替代方案) - 按钮关联的工具提示 - 需要紧贴某个控件显示的弹窗 2. **推荐 `showAtLocation()` 的情况**: - 全屏蒙层弹窗 - 屏幕中央的提示框 - 自定义位置的悬浮窗(如模仿系统Toast) - 需要精确控制屏幕坐标的场景 --- #### 五、常见问题解决方案 1. **位置偏移不准**: ```java // 获取View在屏幕的位置 int[] location = new int[2]; anchorView.getLocationOnScreen(location); int x = location[0]; int y = location[1] + anchorView.getHeight(); popupWindow.showAtLocation(parent, Gravity.NO_GRAVITY, x, y); ``` 2. **Android 7.0+ 位置异常**: ```java if (Build.VERSION.SDK_INT >= 24) { Rect visibleFrame = new Rect(); anchorView.getGlobalVisibleRect(visibleFrame); int height = anchorView.getResources().getDisplayMetrics().heightPixels - visibleFrame.bottom; popupWindow.setHeight(height); popupWindow.showAsDropDown(anchorView); } ``` 3. **添加弹出动画**(引用[4]): ```xml <!-- res/anim/popup_anim.xml --> <set xmlns:android="http://schemas.android.com/apk/res/android"> <translate android:duration="300" android:fromYDelta="-100%" android:toYDelta="0"/> </set> ``` ```java popupWindow.setAnimationStyle(R.style.popup_anim); ``` --- ### 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值