Android PopupWindow怎么合理控制弹出位置(showAtLocation)

说到PopupWindow,应该都会有种熟悉的感觉,使用起来也很简单

// 一个自定义的布局,作为显示的内容
Context context = null;  // 真实环境中要赋值
int layoutId = 0;      // 布局ID
View contentView = LayoutInflater.from(context).inflate(layoutId, null);
      
final PopupWindow popupWindow = new PopupWindow(contentView,
                LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT, true);

popupWindow.setTouchable(true);
// 如果不设置PopupWindow的背景,有些版本就会出现一个问题:无论是点击外部区域还是Back键都无法dismiss弹框
// 这里单独写一篇文章来分析
popupWindow.setBackgroundDrawable(new ColorDrawable());
// 设置好参数之后再show
popupWindow.showAsDropDown(contentView);

如果创建PopupWindow的时候没有指定高宽,那么showAsDropDown默认只会向下弹出显示,这种情况有个最明显的缺点就是:弹窗口可能被屏幕截断,显示不全,所以需要使用到另外一个方法showAtLocation,这个的坐标是相对于整个屏幕的,所以需要我们自己计算位置。

如下图所示,我们可以根据屏幕左上角的坐标A屏幕高宽,点击View的左上角的坐标C点击View的大小以及PopupWindow布局的大小计算出PopupWindow的显示位置B

计算方法源码如下:

    /**
     * 计算出来的位置,y方向就在anchorView的上面和下面对齐显示,x方向就是与屏幕右边对齐显示
     * 如果anchorView的位置有变化,就可以适当自己额外加入偏移来修正
     * @param anchorView  呼出window的view
     * @param contentView   window的内容布局
     * @return window显示的左上角的xOff,yOff坐标
     */
    private static int[] calculatePopWindowPos(final View anchorView, final View contentView) {
        final int windowPos[] = new int[2];
        final int anchorLoc[] = new int[2];
     // 获取锚点View在屏幕上的左上角坐标位置
        anchorView.getLocationOnScreen(anchorLoc);
        final int anchorHeight = anchorView.getHeight();
        // 获取屏幕的高宽
        final int screenHeight = ScreenUtils.getScreenHeight(anchorView.getContext());
        final int screenWidth = ScreenUtils.getScreenWidth(anchorView.getContext());
        contentView.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
        // 计算contentView的高宽
        final int windowHeight = contentView.getMeasuredHeight();
        final int windowWidth = contentView.getMeasuredWidth();
        // 判断需要向上弹出还是向下弹出显示
        final boolean isNeedShowUp = (screenHeight - anchorLoc[1] - anchorHeight < windowHeight);
        if (isNeedShowUp) {
            windowPos[0] = screenWidth - windowWidth;
            windowPos[1] = anchorLoc[1] - windowHeight;
        } else {
            windowPos[0] = screenWidth - windowWidth;
            windowPos[1] = anchorLoc[1] + anchorHeight;
        }
        return windowPos;
    }

接下来调用showAtLoaction显示:

View windowContentViewRoot = 我们要设置给PopupWindow进行显示的Viewint windowPos[] = calculatePopWindowPos(view, windowContentViewRoot);
int xOff = 20;// 可以自己调整偏移
windowPos[0] -= xOff;
popupwindow.showAtLocation(view, Gravity.TOP | Gravity.START, windowPos[0], windowPos[1]);// windowContentViewRoot是根布局View

上面的例子只是提供了一种计算方式,在实际开发中可以根据需求自己计算,比如anchorView在左边的情况,在中间的情况,可以根据实际需求写一个弹出位置能够自适应的PopupWindow。

补充上获取屏幕高宽的代码ScreenUtils.java:

    /**
     * 获取屏幕高度(px)
     */
    public static int getScreenHeight(Context context) {
        return context.getResources().getDisplayMetrics().heightPixels;
    }
    /**
     * 获取屏幕宽度(px)
     */
    public static int getScreenWidth(Context context) {
        return context.getResources().getDisplayMetrics().widthPixels;
    }

Demo截图展示:

看完觉得有用记得点击推荐支持一下,谢谢

Demo下载地址https://github.com/PopFisher/SmartPopupWindow

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏移动开发之家

Android 列表视频的全屏、自动小窗口优化实践

上例牌 github>>>>>>>> https://github.com/CarGuo 对,就是这个郭老司机。

1025
来自专栏用户画像

java 五子棋

1232
来自专栏封碎

Android简单的圆盘形菜单 博客分类: Android Android360

   今天偶然看到一个圆盘形的菜单,还可以转动,感觉挺有意思,然后想了想,做了个简单的效果。       思路是这样的,定一个原点和一个半径,圆的四周均匀...

872
来自专栏向治洪

qq侧滑

上一篇博客带大家实现了:Android 自定义控件打造史上最简单的侧滑菜单 ,有兄弟看了以后说,你这滑动菜单过时了呀~QQ5.0的效果还不错~~嗯,的确,上一...

3126
来自专栏菩提树下的杨过

打印机设置(PrintDialog)、页面设置(PageSetupDialog) 及 RDLC报表如何选择指定打印机

如果一台电脑同时连接多个打印机,而且每个打印机使用的纸张大小各不相同(比如:票据打印钱用的小票专用张,办公打印机用的是A4标准纸),在处理打印类的需求时,如果不...

2347
来自专栏Android干货园

Android源码解析-仿今日头条PagerSlidingTabStrip滑动页面导航效果

版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/lyhhj/article/details/48...

1472
来自专栏TechBox

UITableViewCell系列之(二)视觉差滚动效果前言

1162
来自专栏QQ音乐技术团队的专栏

小窗播放视频的原理和实现(下)

本文对小窗视频播放进行了详细的研究,针对几种实现方案进行了深入的对比分析,进而给出实现小窗视频播放的最优解。其中通过对系统源码的分析,详细探究了如何完美地实现移...

64610
来自专栏移动开发之家

Android 实现视屏播放器、边播边缓存功能、外加铲屎(IJKPlayer)

Android上最为人熟知的MediaPlayer,对,就是这货,在上两篇音频文章中频频露脸的家伙,这次又有它的身影,然而还是这次不讲他,就连他的封装类Vide...

1273
来自专栏我和未来有约会

一个最基本的布局控件-panel

Silverlight做了两个布局的控件了。 Silverlight控件 - Carrousel Silverlight控件 - ScatterView 所...

2765

扫码关注云+社区