一、showAtLocation解析
很多开发者都有使用过PopupWindow,奈何当前论坛很少有正确且全面的解析,关于showAtLocation都是抄袭前篇一律,所以趁着闲暇时间写这篇文章,希望能够记录并且更好得帮助使用PopupWindow。
下面先上源码
可看到showAtLocation接收4个参数,第一个参数是parent,其作用就是获取parent所在view的token,然后通过内部的binder机制传递token与WMS进行交互,目的很简单,就是确定在当前parent所对应的在WMS的窗口位置,并在此弹出Popwindow,而WMS中,token可以理解为识别符号(关于WMS不详诉)。同时为了避免持有外部parent的引用,采取了弱引用的方式。
第二个参数是gravity,就是确定当前坐标系从哪一个地方开始,比如设定Gravity.Start|Gravity.Top,就是从当前窗口的左上角开始计算,对于x轴,右方向为正。对于y轴,下方向为正。值得注意的是,如果设定Gravity.NO_GRAVITY的话,效果等同于Gravity.Start|Gravity.Top,所以开发中可以利用这个进行简单处理
最后是重点的第3个参数与第四个参数,很多博客都很笼统的概述为偏移量,但是怎么偏移都没有很好的解释清楚,非常坑人。
我们以事件驱动去理解这两个参数,假设我们要实现在某一个view的上方或者下方弹出一个PopupWindow,那该怎么做?【不采用showAsDropDown()方式,因为默认弹出向下的弹出,不好兼容我们向上弹出的方式】
如果在view的上方弹出:
y方向的偏移量是:当前view在窗口的高度-Popupwindow(默认wrap_content)的contentView的高度。
如果在view的下方弹出:
y方向的偏移量是:当前view在窗口的高度+view本身的高度。
注意看两个的区别,除了加减不一样之外,最重要的是减数也不一样,一个是contentView的高度,另一个是view本身的高度。
我们看一下图解
在view上方弹出:
可以看到popupWindow的高度应该是当前view在窗口的高度-Popupwindow(默认wrap_content)的contentView的高度。
在view下方弹出
y方向的偏移量是:当前view在窗口的高度+view本身的高度。
所以可以看出,x,y是什么我们可以给出一个结论了,就是PopupWindow左上角相对于窗口的距离!这个距离于第二个gravity的数值也有关系,就相当于在窗口做矩形运算。