Android应用多窗口/浮窗模式下PopupWindow正确定位问题
问题根因
你当前的定位异常核心出在showAsDropDown后调用的update(view, mPlayPopupWidth, mPlayPopupHeight)这行代码:
该重载的update方法在Android 7.0及以上系统的多窗口、自由窗口模式下存在兼容性缺陷,计算位置时会默认使用全局屏幕坐标,不会自动叠加当前应用窗口相对于屏幕的偏移量,最终导致PopupWindow位置偏移。
解决方案
方案1:无需动态调整宽高时直接删除update调用(最优解)
绝大多数场景下不需要在弹出后修改宽高,提前给PopupWindow设置固定宽高即可,修改后代码如下:
// 初始化PopupWindow阶段就设置好固定宽高,不要放到点击事件中重复设置 mPlayPopup.setWidth(mPlayPopupWidth); mPlayPopup.setHeight(mPlayPopupHeight); mPlayButton = new Button(activity); mPlayButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { // 直接调用showAsDropDown即可,无需后续update操作 mPlayPopup.showAsDropDown(view, 10, 10); } });
showAsDropDown方法本身会自动基于锚点View的相对位置计算坐标,天生适配多窗口、浮窗模式的窗口偏移,无兼容性问题。
方案2:需要动态调整宽高时使用坐标重载的update方法
如果确实需要在弹出时动态修改PopupWindow的宽高,不要使用带View参数的update重载,先手动计算锚点View的相对坐标再更新:
mPlayButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { mPlayPopup.showAsDropDown(view, 10, 10); // 获取锚点View在当前应用窗口内的相对坐标 int[] location = new int[2]; view.getLocationInWindow(location); // 计算最终位置:x=锚点x坐标+水平偏移10,y=锚点y坐标+锚点高度+垂直偏移10 int finalX = location[0] + 10; int finalY = location[1] + view.getHeight() + 10; // 用坐标参数的update方法更新,不会出现坐标偏移问题 mPlayPopup.update(finalX, finalY, mPlayPopupWidth, mPlayPopupHeight); } });
补充注意事项
如果你的PopupWindow允许超出当前应用窗口边界显示,可以额外添加mPlayPopup.setClippingEnabled(false)配置,避免系统自动裁剪PopupWindow的内容。
内容的提问来源于stack exchange,提问作者Leszek
相关产品推荐
相关产品推荐

