关于使用PopupWindow的一些问题

1.背景变暗

在弹出PopupWindow的时候,设置Window的alpha(透明度)和dim(暗淡值)两个值。

        final Window window = getWindow();
        final WindowManager.LayoutParams params = window.getAttributes();
        window.addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
        params.dimAmount = 0.7f;
        params.alpha = 0.7f;
        window.setAttributes(params);
        popupWindow.setOnDismissListener(new PopupWindow.OnDismissListener() {
            @Override
            public void onDismiss() {
                params.dimAmount = 1.0f;
                params.alpha = 1.0f;
                window.setAttributes(params);
            }
        });
效果如下图所示:

2.具体位置

设置PoppupWindow在具体位置,可以调用popupWindow.showAtLocation(View, int, int, int)方法。

    /**
     * <p>
     * Display the content view in a popup window at the specified location. If the popup window
     * cannot fit on screen, it will be clipped. See {@link android.view.WindowManager.LayoutParams}
     * for more information on how gravity and the x and y parameters are related. Specifying
     * a gravity of {@link android.view.Gravity#NO_GRAVITY} is similar to specifying
     * <code>Gravity.LEFT | Gravity.TOP</code>.
     * </p>
     *
     * @param parent a parent view to get the {@link android.view.View#getWindowToken()} token from
     * @param gravity the gravity which controls the placement of the popup window
     * @param x the popup's x location offset
     * @param y the popup's y location offset
     */
    public void showAtLocation(View parent, int gravity, int x, int y) {
        showAtLocation(parent.getWindowToken(), gravity, x, y);
    }

其中,参数parent为PopupWindow关联的View;参数gravity为PopupWindow的位置(居左,居中,居右等);参数x为PopupWindow的x坐标偏移量;参数y为PopupWindow的y坐标偏移量。

在上面图中,PopupWindow显示在Button的左边位置,并且与Button对齐,具体代码为:

        int[] location = new int[2];
        button.getLocationInWindow(location);
        popupWindow.showAtLocation(button, Gravity.NO_GRAVITY, location[0] - contentView.getWidth(), location[1] - contentView.getMeasuredHeight() / 2 + button.getHeight() / 2);

注意:当contentView的宽或高为wrap_content时,要先测量contentView的宽高。测量方法如下:

contentView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED),
                View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED));

实际上调用measure()方法时,会去调用onMeasure()方法,然后测量出View的大小。

public final void measure(int widthMeasureSpec, int heightMeasureSpec){}

参数widthMeasureSpec:表示父容器强加给的水平空间
参数heightMeasureSpec:表示父容器强加给的垂直空间

关于View.MeasureSpec.makeMeasureSpec(int, int)方法:

        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << MeasureSpec.MODE_SHIFT) - 1) int size,
                                          @MeasureSpecMode int mode) {}

参数size:是指在某种测量模式的规格大小
参数mode:是指在测量模式
另外,模式只有三种值:

  • UNSPECIFIED:父容器不对View有任何限制,要多大给多大。
  • EXACTLY:父容器检测出View所需要的精确大小,这个时候View的最终大小就是SpecSize(参数size)所指定的值。它对应于LayoutParams中的match_parent和具体的数值这两种模式。
  • AT_MOST:父容器指定了一个可用大小即SpecSize(参数size),View的大小不能大于这个值,具体是什么值要看不同View的具体实现。它对应于LayoutParams中的wrap_content。

3.动画

在使用动画时,如果PopupWindow从底部弹出:

popupWindow.showAtLocation(v.getRootView(), Gravity.BOTTOM, 0, 0);

那么在系统5.0以上,会出现在NavigationBar下面弹出或者被NavigationBar遮挡问题。如下图所示:

针对这个问题有如下解决方案:

在values-21/style.xml中的主题中添加:

<item name="android:windowDrawsSystemBarBackgrounds">false</item>

这个属性指示这个窗口是否负责绘制系统bar的背景。

猜你喜欢

转载自blog.csdn.net/wangjiang_qianmo/article/details/73604500