重力值如何影响Android中弹出窗口的PopupWindow.showAtLocation()方法?

43

不同的Gravity值如何影响Android中的PopupWindow.showAtLocation()?

我找不到有关PopupWindows showAtLocation和Gravity的好文档。

2个回答

74
在尝试使用黑魔法数学计算中心并尝试使用Gravity.TOP对齐视图几个小时后,我发现了一篇使用Gravity.CENTER的文章。我将我的发现记录在此,希望能够节省其他人的痛苦。
popupWindow.showAtLocation(anyViewOnlyNeededForWindowToken, Gravity.CENTER, 0, 0);

视图仅对窗口标记需要,不会影响位置。
重力告诉布局管理器在何处开始坐标系以及如何处理这些坐标。我找不到文档,但是破解后的结果显示:
CENTER将使用弹出窗口的中心点与指定的x,y对齐。因此,0,0位于屏幕中央,不会考虑通知栏的大小调整。

Gravity.CENTER 0,0

  • BOTTOM将弹出窗口的底部与指定的x,y对齐。因此,0,0表示弹出窗口底部与屏幕底部对齐。如果您想要10像素的填充,则y=10(而不是-10)可以将弹出窗口向上移动10像素。

Gravity.BOTTOM 0,10

  • TOP使用弹出窗口的顶部与指定的x,y对齐。因此,0,0表示弹出窗口的顶部与屏幕顶部对齐。如果您想要10像素的填充,则y=10。注意:如果您未处于全屏模式,则还必须针对通知栏进行调整。

Gravity.TOP 0,48

  • 现在Gravity.LEFT和Gravity.RIGHT应该很明显了,对于我的示例图像,它们太大无法适合屏幕,因此它们被夹紧到我正在使用的填充减去屏幕大小。

如何解决使用showAsDropDown时弹出窗口被裁剪(显示在屏幕外)的问题?文档中说不应该发生这种情况,但实际上确实会发生。我尝试在调用showAsDropDown之前和之后分别使用setClippingEnabled(true)和update(),但问题仍然存在。谢谢。 - Ashraf Alshahawy

20
您可以通过调整showAtLocation方法中的Gravity.CENTER来更改PopupWindow的重力:
popupWindow.showAtLocation(anyView, Gravity.CENTER, 0, 0);

以下图片展示效果:

中心

  • Gravity.CENTER

PopupWindow center gravity

边缘

  • Gravity.TOP
  • Gravity.BOTTOM
  • Gravity.LEFT
  • Gravity.RIGHT

PopupWindow edge gravity

角落

  • Gravity.TOP | Gravity.LEFT(上左角)
  • Gravity.TOP | Gravity.RIGHT(上右角)
  • Gravity.BOTTOM | Gravity.LEFT(下左角)
  • Gravity.BOTTOM | Gravity.RIGHT(下右角)

PopupWindow corner gravity

偏移量

您可以通过更改(x,y)偏移量来进一步定位它。

popupWindow.showAtLocation(anyView, gravity, x, y);

例如
popupWindow.showAtLocation(anyView, Gravity.BOTTOM, 0, 300);

PopupWindow bottom gravity with offsets

代码

以下是上述示例的代码。有关更基本的帮助,请参见如何制作简单的Android弹出窗口

int gravity = Gravity.CENTER;

LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
View popupView = inflater.inflate(R.layout.popup_window, null);
int width = LinearLayout.LayoutParams.WRAP_CONTENT;
int height = LinearLayout.LayoutParams.WRAP_CONTENT;
boolean focusable = true;
final PopupWindow popupWindow = new PopupWindow(popupView, width, height, focusable);
popupView.setOnTouchListener(new View.OnTouchListener() {
    @Override
    public boolean onTouch(View v, MotionEvent event) {
        popupWindow.dismiss();
        return true;
    }
});

popupWindow.showAtLocation(anyView, gravity, 0, 0);

参见

  • 如果你想要将弹出窗口锚定到一个视图上,可以使用showAsDropDown

1
如何解决使用showAsDropDown时弹出窗口被裁剪(显示在屏幕外)的问题?文档中说不应该发生这种情况,但实际上确实会发生。我尝试在调用showAsDropDown之前和之后分别使用setClippingEnabled(true)和update(),但问题仍然存在。谢谢。 - Ashraf Alshahawy
@AshrafAlshahawy,我一时也不确定。我建议您为此提出一个新问题,并包括屏幕截图和您的代码。 - Suragch
@AshrafAlshahawy 我也遇到了同样的问题。你解决了吗? - YellowJ

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接