简体   繁体   English

在 Android 中使用 PopupWindow 调暗背景

[英]Dim the background using PopupWindow in Android

Can I dim the background using a PopupWindow instead of a Dialog?我可以使用 PopupWindow 而不是 Dialog 使背景变暗吗? I am asking this because I am using Dialogs but the Dialog doesn't show below the item clicked and with the PopupWindow I already have the popup showing below the item.我问这个是因为我正在使用对话框,但对话框没有显示在单击的项目下方,并且使用 PopupWindow 我已经在项目下方显示了弹出窗口。

I use the following code, and it works well for me.我使用以下代码,它对我来说效果很好。

public static void dimBehind(PopupWindow popupWindow) {
    View container;
    if (popupWindow.getBackground() == null) {
        if (VERSION.SDK_INT >= VERSION_CODES.M){
            container = (View) popupWindow.getContentView().getParent();
        } else {
            container = popupWindow.getContentView();
        }
    } else {
        if (VERSION.SDK_INT >= VERSION_CODES.M) {
            container = (View) popupWindow.getContentView().getParent().getParent();
        } else {
            container = (View) popupWindow.getContentView().getParent();
        }
    }
    Context context = popupWindow.getContentView().getContext();
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    WindowManager.LayoutParams p = (WindowManager.LayoutParams) container.getLayoutParams();
    p.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;
    p.dimAmount = 0.3f;
    wm.updateViewLayout(container, p);
}

From this answer .这个答案

Update:更新:

The fdermishin's answer below is better.下面的 fdermishin 的答案更好。 I have tested it backwards to API level 19 and it works well.我已经将它向后测试到 API 级别 19,它运行良好。

If you are using Kotlin, it is better to use it as Kotlin extension:如果您使用 Kotlin,最好将其用作 Kotlin 扩展:

//Just new a kotlin file(e.g. ComponmentExts),
//copy the following function declaration into it
/**
 * Dim the background when PopupWindow shows
 */
fun PopupWindow.dimBehind() {
    val container = contentView.rootView
    val context = contentView.context
    val wm = context.getSystemService(Context.WINDOW_SERVICE) as WindowManager
    val p = container.layoutParams as WindowManager.LayoutParams
    p.flags = p.flags or WindowManager.LayoutParams.FLAG_DIM_BEHIND
    p.dimAmount = 0.3f
    wm.updateViewLayout(container, p)
}

//then use it in other place like this:
popupWindow.dimBehind()

It seems that I figured out how to get rid of API version checks.似乎我想出了如何摆脱 API 版本检查的方法。 Using container = popupWindow.getContentView().getRootView() solves the problem, however I haven't tested it for old APIs yet.使用container = popupWindow.getContentView().getRootView()解决了这个问题,但是我还没有针对旧的 API 测试它。 Adapting Junyue Cao's solution:适配曹骏越的方案:

public static void dimBehind(PopupWindow popupWindow) {
    View container = popupWindow.getContentView().getRootView();
    Context context = popupWindow.getContentView().getContext();
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    WindowManager.LayoutParams p = (WindowManager.LayoutParams) container.getLayoutParams();
    p.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
    p.dimAmount = 0.3f;
    wm.updateViewLayout(container, p);
}

JiaJiaGu's solution works but the popupWindow will overlap with navigation bar since it clears all the other flags. JiaJiaGu 的解决方案有效,但 popupWindow 将与导航栏重叠,因为它清除了所有其他标志。

So I change a little bit here:所以我在这里稍微改变一下:

public static void dimBehind(PopupWindow popupWindow) {
    View container;
    if (VERSION.SDK_INT >= VERSION_CODES.M){
        container = (View) popupWindow.getContentView().getParent();
    } else {
        container = popupWindow.getContentView();
    } 
    if (popupWindow.getBackground() != null) {
        container = container.getParent()
    }
    Context context = popupWindow.getContentView().getContext();
    WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
    WindowManager.LayoutParams p = (WindowManager.LayoutParams) container.getLayoutParams();
    p.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND; // add a flag here instead of clear others
    p.dimAmount = 0.3f;
    wm.updateViewLayout(container, p);
}

I post a new answer because I can't comment on JiaJiaGu's answer.我发布了一个新答案,因为我无法评论 JiaJiaGu 的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM