我们仍未知道的popWindow 7.0 8.0位置显示错误

popWindow一个神奇的控件,为了记录自己曾解决过的问题,也避免其他小哥遇到一样的问题,故留下博客进行记录。

最近在写一个下拉框的时候,测试小哥找到我说7.0,7.1,8.0的显示效果不一致……

我当时的心情是……&¥%#&&(&

好吧,当遇这样的问题,第一反应是不要慌……不要慌……甩锅……不对,是分析并解决问题。由于各种原因我这里就不上产品的效果,取而代之用一个抽取了特征的demo来代替说明问题。(其实在验证问题时,抽取出相关因素用demo进行还原调试,不失为一个很好的办法,毕竟有些工程光编译就要7、8分钟,你会感受到被编译支配的恐惧。)

1、问题展示

正常效果是这样的:

8.0手机上的效果是这样的:

2、问题的尝试与分析

好了,上代码吧。

    public void popWindow(View view) {
        // 将布局文件转换成View对象,popupview 内容视图
        View mPopView = getLayoutInflater().inflate(R.layout.pop_window_item, null);
        // 将转换的View放置到 新建一个popuwindow对象中
        PopupWindow mPopupWindow = new PopupWindow(mPopView,
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.MATCH_PARENT);
        
        mPopupWindow.showAsDropDown(view);
    }

从代码上看貌似没什么问题,那么我们就要考虑是否是不同api之间的问题了。

这里经过尝试当高度使用WRAP_CONTENT而不是MATCH_PARENT则不会出现问题,那么我们可以猜想出showAsDropDown的anchor定位view并没有错,使用WRAP_CONTENT计算的起始下标为指定view的左下坐标点。

public void showAsDropDown(View anchor) {
        throw new RuntimeException("Stub!"); 
}

而MATCH_PARENT的坐标起始点恐怕已经被设置成状态栏下的左上顶部坐标点了吧。

3、解决方案

自定义一个继承PopWindow的类,并复写showAsDropDown()方法,你可以复写showAsDropDown(View anchor),public void showAsDropDown(View anchor, int xoff, int yoff) 等方法,具体看各自调用的需求。

public class CompatiblePopWindow extends PopupWindow {
    public CompatiblePopWindow(View contentView, int width, int height) {
        super(contentView, width, height);
    }

    @Override
    public void showAsDropDown(View anchor) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            Rect compatibleFix = new Rect();
            anchor.getGlobalVisibleRect(compatibleFix);
            int height = anchor.getResources().getDisplayMetrics().heightPixels - compatibleFix.bottom;
            this.setHeight(height);
        }
        super.showAsDropDown(anchor);
    }

}
    /**Button弹出popupWindow的点击事件
     */
    public void popWindow(View view) {
        // 将布局文件转换成View对象,popupview 内容视图
        View mPopView = getLayoutInflater().inflate(R.layout.pop_window_item, null);
        // 将转换的View放置到 新建一个popuwindow对象中
        CompatiblePopWindow popupWindow = new CompatiblePopWindow(mPopView,
                LinearLayout.LayoutParams.MATCH_PARENT,
                LinearLayout.LayoutParams.WRAP_CONTENT);

        popupWindow.showAsDropDown(view);
    }

附赠一个简单PopWindow类的封装调用,该封装类和使用demo可以下载附件获取。

    /**Button弹出popupWindow的点击事件
     */
    public void popWindow(View view) {
        // 将布局文件转换成View对象,popupview 内容视图
        View mPopView = getLayoutInflater().inflate(R.layout.pop_window_item, null);

        //附带库的使用方法
        TomesPopWindow mPopWindow = new TomesPopWindow.PopupWindowBuilder(this)
                .setView(mPopView)
                .size(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT)
                .create()
                .showAsDropDown(view,0,0);
    }

Demo下载

猜你喜欢

转载自blog.csdn.net/qq_35559358/article/details/84315691