PopupWindow在Android7.0和7.1系统上显示位置不正确的问题解决

时间:2021-03-24 10:54:53

前言

今天做项目需要用到PopupWindow,但发现其显示的位置在Android7.0以下系统正常,在7.0和7.1系统显示不正常,点击“打开POP”按钮效果对比如下:

4.1系统

PopupWindow在Android7.0和7.1系统上显示位置不正确的问题解决

7.0系统

PopupWindow在Android7.0和7.1系统上显示位置不正确的问题解决

7.1系统

PopupWindow在Android7.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 {

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);
}
}
参考链接: http://blog.csdn.net/ithouse/article/details/56853948
方案二:

直接在需要显示的地方判断显示的方式

if (Build.VERSION.SDK_INT == 24) {
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));
}
参考链接: http://blog.csdn.net/m190607070/article/details/58618662

方案三:

使用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)
{
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);
}
参考链接: http://blog.csdn.net/dxxs19/article/details/53572833

通过上述方案修正后,在7.1上测试如图
PopupWindow在Android7.0和7.1系统上显示位置不正确的问题解决