PopupWindow 全屏问题两种解决方案

当使用PopupWindow并调用showAsDropDown方法时,遇到了意外地填充整个屏幕的问题。解决方法包括计算PopupWindow的高度为LinearLayout高度减去控件底部高度,并重写showAsDropDown方法以实现正常显示。

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

点击调用showAsDropDown(view)后,PopupWindow 填充了整个屏幕,如图所示

解决后正常显示,如图2所示

图2

 

解决办法:

  1. 计算PopupWindow要显示的高度   

       

     popupwindow的高度= LinearLayout的高度控件的bottom的高度

    void showOrderItemsPPWindow() {
            final View contentView = LayoutInflater.from(DeliveOrderActivity.this).inflate(R.layout.ppw_order_pick_type, null, false);
    //       popupwindow的高度 = LinearLayout的高度 - 控件的bottom的高度
            int height = deliveLlayout.getHeight() - orderItemBtn.getBottom();
            final PopupWindow window = new PopupWindow(contentView, LinearLayout.LayoutParams.MATCH_PARENT, height);
    
    
    
            window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
            window.setOutsideTouchable(true);
            window.setTouchable(true);
            window.showAsDropDown(orderItemBtn, 0, 0, Gravity.BOTTOM);
            window.setBackgroundDrawable(new ColorDrawable(Color.BLACK));
    
            LinearLayout linearLayout = contentView.findViewById(R.id.full_llayout);
            linearLayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    window.dismiss();
                }
            });
            window.setOnDismissListener(new PopupWindow.OnDismissListener() {
                @Override
                public void onDismiss() {
    
                }
            });
        }

     

  2.  

    重写Popupwindow的showAsDropDown方法

    public class MPopupWindow extends PopupWindow {
    
    
        public MPopupWindow(View contentView, int width, int height) {
            super(contentView, width, height);
        }
    
        @Override
        public void showAsDropDown(View anchor) {
            if (Build.VERSION.SDK_INT >= 24){
                Rect ew = new Rect();
                anchor.getGlobalVisibleRect(ew);
                int height = anchor.getResources().getDisplayMetrics().heightPixels - ew.top;
                setHeight(height);
            }
    
            super.showAsDropDown(anchor);
        }
    }

     

        void showOrderItemsPPWindow() {
            final View contentView = LayoutInflater.from(DeliveOrderActivity.this).inflate(R.layout.ppw_order_pick_type, null, false);
            final MPopupWindow window = new MPopupWindow(contentView, LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT);
            window.setBackgroundDrawable(new ColorDrawable(Color.TRANSPARENT));
            window.setOutsideTouchable(true);
            window.setTouchable(true);
            window.showAsDropDown(orderItemBtn);
            window.setBackgroundDrawable(new ColorDrawable(Color.BLACK));
    
            LinearLayout linearLayout = contentView.findViewById(R.id.full_llayout);
            linearLayout.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    window.dismiss();
                }
            });
            window.setOnDismissListener(new PopupWindow.OnDismissListener() {
                @Override
                public void onDismiss() {
    
                }
            });
        }

     

     

<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 PopupWindow 的 showAsDropDown 与 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、付费专栏及课程。

余额充值