前言
今天做项目需要用到PopupWindow,但发现其显示的位置在Android7.0以下系统正常,在7.0和7.1系统显示不正常,点击“打开POP”按钮效果对比如下:
4.1系统
7.0系统
7.1系统
代码如下:
public class MainActivity extends AppCompatActivity {
private LinearLayout popupDisplay;
private PopupWindow popupWindow;
private Button button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
popupDisplay = (LinearLayout) UiUtil.inflate((R.layout.popup));
popupWindow = new PopupWindow(popupDisplay, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, true);
popupWindow.setTouchable(true);
popupWindow.setOutsideTouchable(true);
popupWindow.setBackgroundDrawable(new BitmapDrawable(getResources(), (Bitmap) null));
button = (Button) findViewById(R.id.btn);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
popupWindow.showAsDropDown(button);
}
});
}
}
原因
详细原因请移步:PopupWindow 在 Android N(7.0) 的兼容性问题
解决
看了许多关于PopupWindow的bug的相关文章,分享如下
方案一:
自定义一个类继承PopupWindow,重写构造方法和需要用到的showAsDropDown()方法
public class SFPopupWindow extends PopupWindow {参考链接: http://blog.csdn.net/ithouse/article/details/56853948
public SFPopupWindow(Context context) {
super(context, null);
}
@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) {参考链接: http://blog.csdn.net/m190607070/article/details/58618662
int[] a = new int[2];
m.get().getLocationInWindow(a);
popupWindow.showAtLocation(getWindow().getDecorView(), Gravity.NO_GRAVITY, 0, a[1]);
popupWindow.update();
} else {
popupWindow.showAsDropDown(v, 0, -Utils.dip2px(46));
}
方案三:
使用showAtLocation()显示
Android 7.0之前,在指定位置弹出popupwindow可以用showAsDropDown(View anchor, int xoff, int yoff),showAtLocation(View parent, int gravity, int x, int y)。但在android 7.0上,用showAsDropDown()在popupwindow为全屏时,会有弹出位置异常情况,需用showAtLocation()才能正常显示:
if (Build.VERSION.SDK_INT < 24)参考链接: http://blog.csdn.net/dxxs19/article/details/53572833
{
dropListPopupWindow.showAsDropDown(this, 0, 5);
}
else
{
// 适配 android 7.0
int[] location = new int[2];
getLocationOnScreen(location);
int x = location[0];
int y = location[1];
Log.e(getClass().getSimpleName(), "x : " + x + ", y : " + y);
dropListPopupWindow.showAtLocation(this, Gravity.NO_GRAVITY, 0, y + getHeight() + 5);
}
通过上述方案修正后,在7.1上测试如图