Android PopupWindow的显示位置说明
位置
- PopupWindow最关键的就是要让窗体显示在合适的位置,而设置位置的有两个方法,一个是showAtLocation,一个是showAsDropDown
public void showAtLocation(View parent, int gravity, int x, int y)
public void showAsDropDown(View anchor, int xoff, int yoff)
showAsDropDown
-
其中showAtLocation是相对于整个窗体来说的,而showAsDropDown则是以第一个参数的view作为锚点,通过xoff,yoff偏移量来控制PopupWindow的绘制起点
-
如上图,比如我们想让PopupWindow显示在某个view(我们称之为anchor)的正上方,那么我们先要知道anchor这个view的左下角(注意是左下角)的坐标,然后根据PopupWindow要显示的位置计算PopupWindow的左上角的坐标,这两个坐标的差值就是xoff,yoff的值了
-
例如你已经知道anchor的左下角坐标为(100,100),而PopupWindow的左上角坐标为(80,50),那么xoff = 80 - 100= -20,yoff = 50 - 100 = -50
-
因此我们只要在同个坐标系下得到anchor的左下角坐标和popupwindow的左上角坐标,则xoff和yoff即为popupwindow减去anchor的差值
if (show) {
if (bottomMembersPopupWindow != null && bottomMembersPopupWindow.isShowing()) {
return;
}
LayoutInflater inflater = (LayoutInflater) getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE);
View vPopupWindow = inflater.inflate(R.layout.popup_hint, null, false);//引入弹窗布局
bottomMembersPopupWindow = new PopupWindow(vPopupWindow, ActionBar.LayoutParams.WRAP_CONTENT, ActionBar.LayoutParams.WRAP_CONTENT, true);
bottomMembersPopupWindow.setAnimationStyle(-1);//默认动画
bottomMembersPopupWindow.setOutsideTouchable(true);
vPopupWindow.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
int yDelay = -5;//y方向偏移,负数表示向上偏移
bottomMembersPopupWindow.showAsDropDown(ivMembers, -(vPopupWindow.getMeasuredWidth() - ivMembers.getMeasuredWidth()) / 2, -(vPopupWindow.getMeasuredHeight() + ivMembers.getMeasuredHeight()) + yDelay);
} else {
if (bottomMembersPopupWindow != null) {
bottomMembersPopupWindow.dismiss();
}
}
showAtLocation
public void showAtLocation(View parent, int gravity, int x, int y);
- 参数parent是能拿到getWindowToken()的view即可,因此只要是当前继承View的任何子类都可以,可以是TextView,ImageView,RelativeLayout等,很多人一看到parent都会想当然以为是ViewGroup类型的才可以,其实不然,它只是为了确定是哪个窗体而已
- gravity则是指示窗体坐标原点在哪里,默认android是以窗体左上角为原点,也就是NO_GRAVITY
- Gravity.NO_GRAVITY其实等同于Gravity.LEFT | Gravity.TOP,都表示左上角,那么相对的Gravity.RIGHT | Gravity.TOP就表示以右上角为原点了,Gravity.LEFT 就是以(0,窗体高度一半)为原点,其他以此类推
- 不过我们一般使用的就是Gravity.NO_GRAVITY和Gravity.CENTER,即以左上角为原点或以窗体中心点为原点
- 接下来的x和y参数其实就依赖gravity参数选择的参考系了,然后(x,y)就是在选定的gravity的参考系中的坐标,一般情况下建议你使用Gravity.NO_GRAVITY,这样就跟android的左上角为原点的参考系一样了,易于理解且不容易出错
- 最后,不管怎样,即使你的x,y坐标实际上已经超出了窗体,showAtLocation也会把它显示在窗体内
- 如果想超出窗体,那么就得设置PopupWindow.setClippingEnabled(false),为false就可以超出窗体了,不过超出窗体那部分是不可见的
其他
- 如果想在popupwindow显示后更改位置,则可以调用update接口,重复调用showAtLocation和showAsDropDown是不会更新位置的,因为内部判断正在显示的话就返回不会往下执行了
- 在调用showAsDropDown时在边界地带会发现内容被挤压截断,此时只需要再次调用update接口即可