弹出PopupWindow后让背景变暗的方法

在Android上使用AlertDialog和PopupWindow都可以很方便的实现弹窗,AlertDialog弹出后背景会变暗,而PopupWindow不具有此特性。StackOVerflow上的这个问题里给出了三种方法以实现弹出PopupWindow后让背景变暗的效果,整理如下。


1. 方法一

使用WindowManager.LayoutParams.FLAG_DIM_BEHIND可以实现变暗的效果。

//bgcolor 代表透明程度,范围为0 - 1.0f
private void darkenBackground(Float bgcolor) {
        WindowManager.LayoutParams lp = mMainActivity.getWindow().getAttributes();
        lp.alpha = bgcolor;
        mMainActivity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
        mMainActivity.getWindow().setAttributes(lp);
}

具体用法:

//退出pupouwindow时调用setOnDismissListener(),传入1.0f

if (mShowPopupWindow == null) {
            mShowPopupWindow = new PopupWindow(view, ViewGroup.LayoutParams.MATCH_PARENT,
                    ViewGroup.LayoutParams.WRAP_CONTENT);
            mShowPopupWindow.setOnDismissListener(() -> darkenBackground(1f));
            mShowPopupWindow.setBackgroundDrawable(ContextCompat.getDrawable(mMainActivity, R.color.common_white));
            mShowPopupWindow.setFocusable(true);
  
          mShowPopupWindow.setOutsideTouchable(true);
 }


//显示pupouwindow时传入0.5f
darkenBackground(0.5f);

2. 方法二

为 RootView 的 ViewGroupOverlay 添加黑色 Drawable 并修改其透明度,也可以实现让整个背景窗口的效果。只适用于 API Level 18 及以上。

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public void applyDim(float dimAmount){
    ViewGroup parent = (ViewGroup) getWindow().getDecorView().getRootView();
    Drawable dim = new ColorDrawable(Color.BLACK);
    dim.setBounds(0, 0, parent.getWidth(), parent.getHeight());
    dim.setAlpha((int) (255 * dimAmount));
    ViewGroupOverlay overlay = parent.getOverlay();
    overlay.add(dim);
}
 
@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public void clearDim() {
    ViewGroup parent = (ViewGroup) getWindow().getDecorView().getRootView();
    ViewGroupOverlay overlay = parent.getOverlay();
    overlay.clear();
}

3. 方法三

使用 FrameLayout 作为背景布局的 Root,并设置 FrameLayout 的 foreground 为黑色不透明的 shape,之后就可以通过修改 shape 的透明度,让整个窗口变暗。

  所使用的的 shape (/drawable/dim.xml)如下:

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
    <solid android:color="#000000" />
</shape>

注意其中颜色为黑色(#000000),没有指定Alpha通道(透明度)的值。如果在这里指定了Alpha通道,如使用#ff000000,该Alpha通道的值(0xff)就会固定,无法再通过setAlpha()方法设置。

  把要变暗的区域放在 FrameLayout 中,并设置 FrameLayout 的 foreground 为上面定义的 dim.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:foreground="@drawable/dim"
    tools:foreground="">
 
    ...
 
</FrameLayout>

由于 dim.xml 是不透明的黑色,这里还设置了tools:foreground="",以免在Preview窗口一团黑。

  同样由于 dim.xml 是黑色的,在初始化时记得首先把它设置为透明:

mContainer = (FrameLayout) findViewById(R.id.container);
mContainer.getForeground().setAlpha(0);

然后就可以通过setAlpha()让 FrameLayout 区域变暗或恢复:

mContainer.getForeground().setAlpha(127);
mContainer.getForeground().setAlpha(0);

3. 方法四

使用2个弹出窗口而不是一个。第一个弹出窗口只是一个带有半透明背景的虚拟视图,可以提供暗淡的效果。第二个弹出窗口才是你想要的弹出窗口。

创建弹窗时的顺序: 显示虚拟弹出窗口1秒后显示预期的弹出窗口。

销毁弹窗时的顺序: 关闭弹出窗口,然后弹出虚拟弹出窗口。

链接这两者的最好方法是添加一个OnDismissListener并重写onDismiss()方法。

虚拟弹出窗口:

fadepopup.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" 
    android:id="@+id/fadePopup"
    android:background="#AA000000">
</LinearLayout>

显示淡入淡出以调暗背景

private PopupWindow dimBackground() {

    LayoutInflater inflater = (LayoutInflater) EPGGRIDActivity.this
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    final View layout = inflater.inflate(R.layout.fadepopup,
            (ViewGroup) findViewById(R.id.fadePopup));
    PopupWindow fadePopup = new PopupWindow(layout, windowWidth, windowHeight, false);
    fadePopup.showAtLocation(layout, Gravity.NO_GRAVITY, 0, 0);
    return fadePopup;
}



  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值