PopupWindow.showAtLocation理解

最近开发一个新功能的时候遇到了popupWindow显示位置问题,于是好好的研究了下使用方法和源码,发现之前对showAtLocation一直是错误的理解。


showAtLocation 是popupWinow的一个public方法,用于在一个特定的问题显示contentView。

这个方法一共有4个参数:public void showAtLocation(View parent, int gravity, int x, int y)

  • parent : popupWindow通过这个参数获得当前窗口的令牌,从而确定所显示的窗口,实际显示的问题与该参数无关。
  • gravity :一共有9种参数组合,所有的参数组合均是以当前屏幕为基准(非当前窗口)
  • x 和 y :偏移量
popupWindow具体的显示位置绝大多数情况下主要取决于后三个参数。
  • Gravity.NO_GRAVITY :显示效果同 Gravity.LEFT | Gravity.TOP
  • Gravity.LEFT:以屏幕左边中间位置为参照物
  • Gravity.TOP:以屏幕顶部中间位置为参照物
  • Gravity.RIGHT:以屏幕右侧中间位置为参照物
  • Griavity.BOTTOM:以屏幕顶部中间为参照物
  • Gravity.LEFT | Gravity.TOP:以屏幕左上角为参照物
  • Gravity.RIGHT | Gravity.TOP :以屏幕右上角为参照物
  • Gravity.LEFT | Gravity.BOTTOM :以屏幕左下角为参照物
  • Gravity.RIGHT | Gravity.BOTTOM :以屏幕右下角为参照物
  • x :x < 0时,向左偏移, x >0 时,向右偏移
  • y :显示效果受gravity参数影响。当参数不带Gravity.BOTTOM时,y < 0,向上偏移, y > 0 ,向下偏移;当参数带有Gravity.BOTTOM时, y < 0,向下偏移,y > 0,向下偏移

测试代码如下
    @Override
    public void onClick(View v) {
        PopupWindow popupWindow = new PopupWindow();
        Button button = new Button(this);
        button.setBackgroundColor(Color.YELLOW);
        int width = ViewGroup.LayoutParams.WRAP_CONTENT;
        int height = ViewGroup.LayoutParams.WRAP_CONTENT;
        popupWindow.setWidth(width);
        popupWindow.setHeight(height);
        ViewGroup.LayoutParams lp = new ViewGroup.LayoutParams(width,height);
        button.setLayoutParams(lp);
        popupWindow.setContentView(button);
        int x = 0;
        int y = 0;
        int gravity = Gravity.NO_GRAVITY;
        //popupWindow.setClippingEnabled(false);
        switch (v.getId()){
            case R.id.top:
                gravity = Gravity.TOP;
                button.setText("TOP");
                break;
            case R.id.center:
                break;
            case R.id.bottom:
                gravity = Gravity.BOTTOM;
                button.setText("BOTTOM");
                break;
            case R.id.left:
                gravity = Gravity.LEFT;
                button.setText("LEFT");
                break;
            case R.id.right:
                gravity = Gravity.RIGHT;
                button.setText("RIGHT");
                break;
            case R.id.right_bottom:
                gravity = Gravity.RIGHT|Gravity.BOTTOM;
                button.setText("RIGHT|BOTTOM");
                break;
            case R.id.right_top:
                gravity = Gravity.RIGHT|Gravity.TOP;
                button.setText("RIGHT|TOP");
                break;
            case R.id.left_bottom:
                gravity = Gravity.LEFT|Gravity.BOTTOM;
                button.setText("LEFT|BOTTOM");
                break;
            case R.id.left_top:
                gravity = Gravity.LEFT|Gravity.TOP;
                button.setText("LEFT| TOP");
                break;
        }
        popupWindow.showAtLocation(v,gravity,x,y);
    }


布局文件如下

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.justwen.demo.popupwindow.PopupWindowActivity">

    <Button
        android:onClick="onClick"
        android:id="@+id/top"
        android:layout_centerHorizontal="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:onClick="onClick"
        android:id="@+id/center"
        android:layout_centerInParent="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:onClick="onClick"
        android:id="@+id/bottom"
        android:layout_alignParentBottom="true"
        android:layout_centerHorizontal="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:onClick="onClick"
        android:id="@+id/left"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:onClick="onClick"
        android:id="@+id/right"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:onClick="onClick"
        android:id="@+id/left_top"
        android:layout_alignParentLeft="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:onClick="onClick"
        android:id="@+id/left_bottom"
        android:layout_alignParentLeft="true"
        android:layout_alignParentBottom="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

    <Button
        android:onClick="onClick"
        android:id="@+id/right_top"
        android:layout_alignParentRight="true"
        android:layout_alignParentTop="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <Button
        android:onClick="onClick"
        android:id="@+id/right_bottom"
        android:layout_alignParentRight="true"
        android:layout_alignParentBottom="true"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />



</RelativeLayout>




从上面的截图可以看出一个问题,当gravity参数带有Gravity.TOP时候,popupWindow都未超过状态栏,而我们之前有提到gravity参数是以屏幕为基准的,当前x,y均为0的时候,理论上应该位于屏幕顶端。这就与第一个view参数有关了,虽然popupWindow是以屏幕为基准的,但是却是显示在view所在的窗口,是不能超出这个窗口的。类似于“Gravity.LEFT, X< 0” 或者 “Gravity.BOTTOM,y < 0" 的组合,popupWindow同样不会超出当前窗口。


所以Google提供了一个方法,让popupWindow能够超出当前窗口,显示实际的位置
popupWindow.setClippingEnabled(false);
效果如图





  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值