PopupWindow显示位置错乱,真正的终极方案。

测试小姐姐在华为手机上 PopupWindow弹出位置 直接置顶了,但是我的开发机(小米9)却按照代码的意志显示在titleBar之下。

效果类似这样:
PopupWindow显示位置错乱,真正的终极方案。_第1张图片
谷歌一把 ,各种吐槽该问题。

大神们的主流解决方案,主要分两种,
①重写showAsDropDown(),以24为界限,区别对待;
②调用show的时候,SDK>24的时用showAtLocation()替代showAsDropDown();

我先把大婶们的各类终极版的方案代码贴出来:

	@Override
    public void showAsDropDown(View anchor) {
        if(Build.VERSION.SDK_INT >= 24) {
            Rect rect = new Rect();
            anchor.getGlobalVisibleRect(rect);
            int h = anchor.getResources().getDisplayMetrics().heightPixels - rect.bottom;
            setHeight(h);
        }
        super.showAsDropDown(anchor);
}

或者

if (Build.VERSION.SDK_INT < 24) {
            popupWindow.showAsDropDown(anchor);
        } else {
            int[] location = new int[2];
            anchor.getLocationOnScreen(location);
            int y = location[1];
            popupWindow.showAtLocation(anchor, Gravity.NO_GRAVITY, 0, y + anchor.getHeight());
        }

各种尝试,修改,然并卵,统统都不管用。

要么popupWin位置被顶上去,要么阴影底部有白边,要么是虚拟键滑动隐藏时,阴影底部露出白边,虚拟键动态显示时,popupWin被顶上去。各种终极版的方案,并未终结该问题。

显然是popupWin高度计算出问题了,不同手机现象不一,又是让人头大且脱发的适配问题,怎么办呢?
PopupWindow显示位置错乱,真正的终极方案。_第2张图片
话不多说,直奔主题,我是如何解决的?

项目需求是要求上面是筛选弹窗,下层是列表,那么列表RecyclerView怎么做到不白边的?已知RecyclerView高度MATCH_PARENT,且PopupWin与背景RecyclerView等高,那我直接把RecyclerView高度设置给PopupWindow就好了。试了一下,果然完美终结该问题。

请看在华为荣耀8.安卓8.0系统上测试效果图:(请忽略该app是啥,这个不重要)

具体实现步骤

代码思路:
1.在popupWin.show 之前,把与她等高的View(此处指RecyclerView)高度通过setHeight赋值。等show时,高度就生效了;
2.当用户手动显示或隐藏虚拟键时候,需要根据与之等高View高度变化再次动态设置popuWin高度,此时一定是显示状态时候设置,如隐藏就不再考虑。

最重要的伪代码送上:

    private void test() {

        tvTitle.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (!popupWindow.isShowing()) {
                    //设置高度,不立即生效,调用show之后,才生效
                    popupWindow.setHeight(recyclerView.getHeight());
                    popupWindow.showAsDropDown(anchor);
                } else {
                    popupWindow.dismiss();
                }
            }
        });
        //监听RecyclerView高度,动态赋值给popupWin
        recyclerView.addOnLayoutChangeListener(new View.OnLayoutChangeListener() {
            @Override
            public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) {
                if (popupWindow.isShowing()) {
                    //设置高度并生效
                    popupWindow.update(ViewGroup.LayoutParams.MATCH_PARENT, recyclerView.getHeight());
                }
            }
        });
    }

你可能感兴趣的:(Android)