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);
}