问题:当在自定义的PopupWindow中setHeight(ViewGroup.LayoutParams.MATCH_PARENT)时,在7.0以下调用popupWindow.showAsDropDown方法时显示正常,但在7.0及以上调用时显示不正常(PopupWindow没有显示在控件下方,而是从屏幕顶部开始显示)
解析:从7.0的源码中去发现问题所在,从而找到解决办法。

在图1中1的位置是寻找PopupWindow在屏幕中的位置,也是出现问题所在。接下来,我们去详细看看该方法。

图2中1的位置appScreenLocation获取的是DecorView在整个屏幕的位置(x:0,y:0);2的位置screenLocation获取的是要显示PopupWindow的view在屏幕中的位置(view.x,view.y);3的位置drawingLocation获取的是开始绘制的位置(和screenLocation一致);4的位置outParams.x和outParams.y获取的是popupWindow显示的位置。5的位置由于height设置成MATCH_PARENT,所以导致outParams.height等于屏幕的高度。我们继续沿着方法查看:

在图3中正是由于height的高度是屏幕的高度从而不满足height<=spaceBelow,只能继续向下走:

在图4中我们发现最后outParams.y被调整到outParams.y=0;至此导致整个PopupWindow的显示覆盖了view,在屏幕顶部显示。
发现了问题所在,那么我们又如何解决呢?
既然是在positionInDisplayVertical方法中调整outParmas.y导致的,那么我们不走这个方法不就可以了吗?为此我们重新回到图3中

在图3.2中我们发现只要在1或2出返回即可,随后可以看到在2中判断的是popupWindow的高度和view在y轴上的位置,在大多数情况下不满足,所以在1处做文章保证height<=spaceBelow就可以了,所以popupWindow的最大高度应该是屏幕的高度-view的高度。
解决办法如下:
1、当setHeight(MATCH_PARENT)时在showAsDropDown方法中重新设置下高度即可(比较适用于有统一处理的PopupWindow)

2、在setHeight时不在设置成MATCH_PARENT,而设置成setHeight(context.getResources().getDisplayMetrics().heightPixels - anchor.getHeight())
网友评论