androiddialogpopupwindowandroid-dialogandroid-popupwindow

Dim the background using PopupWindow in Android


Can I dim the background using a PopupWindow instead of a 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.


Solution

  • 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. I have tested it backwards to API level 19 and it works well.

    If you are using Kotlin, it is better to use it as Kotlin extension:

    //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()