The question was about the Popupwindow class, yet everybody has given answers that use the Dialog class. Thats pretty much useless if you need to use the Popupwindow class, because Popupwindow doesn't have a getWindow() method.
I've found a solution that actually works with Popupwindow. It only requires that the root of the xml file you use for the background activity is a FrameLayout. You can give the Framelayout element an android:foreground tag. What this tag does is specify a drawable resource that will be layered on top of the entire activity (that is, if the Framelayout is the root element in the xml file). You can then control the opacity (setAlpha()) of the foreground drawable.
You can use any drawable resource you like, but if you just want a dimming effect, create an xml file in the drawable folder with the <shape> tag as root.
(See http://developer.android.com/guide/topics/resources/drawable-resource.html#Shape for more info on the shape element).
Note that I didn't specify an alpha value in the color tag that would make the drawable item transparent (e.g #ff000000). The reason for this is that any hardcoded alpha value seems to override any new alpha values we set via the setAlpha() in our code, so we don't want that.
However, that means that the drawable item will initially be opaque (solid, non-transparent). So we need to make it transparent in the activity's onCreate() method.
Another trick is to use 2 popup windows instead of one. The 1st popup window will simply be a dummy view with translucent background which provides the dim effect. The 2nd popup window is your intended popup window.
Sequence while creating pop up windows:
Show the dummy pop up window 1st and then the intended popup window.
Sequence while destroying:
Dismiss the intended pop up window and then the dummy pop up window.
The best way to link these two is to add an OnDismissListener and override the onDismiss() method of the intended to dimiss the dummy popup window from their.
Since PopupWindow just adds a View to WindowManager you can use updateViewLayout (View view, ViewGroup.LayoutParams params) to update the LayoutParams of your PopupWindow's contentView after calling show..().
Setting the window flag FLAG_DIM_BEHIND will dimm everything behind the window. Use dimAmount to control the amount of dim (1.0 for completely opaque to 0.0 for no dim).
Keep in mind that if you set a background to your PopupWindow it will put your contentView into a container, which means you need to update it's parent.
PopupWindow popup = new PopupWindow(contentView, width, height);
popup.setBackgroundDrawable(null);
popup.showAsDropDown(anchor);
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams p = (WindowManager.LayoutParams) contentView.getLayoutParams();
// add flag
p.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
p.dimAmount = 0.3f;
wm.updateViewLayout(contentView, p);
Marshmallow Update:
On M PopupWindow wraps the contentView inside a FrameLayout called mDecorView. If you dig into the PopupWindow source you will find something like createDecorView(View contentView).The main purpose of mDecorView is to handle event dispatch and content transitions, which are new to M. This means we need to add one more .getParent() to access the container.
With background that would require a change to something like:
ok, so i follow uhmdown's answer for dimming background activity when pop window is open. But it creates problem for me. it was dimming activity and include popup window (means dimmed-black layered on both activity and popup also, it can not be separate them).
so i tried this way,
create an dimming_black.xml file for dimming effect,
For me, something like Abdelhak Mouaamou's answer works, tested on API level 16 and 27.
Instead of using popupWindow.getContentView().getParent() and casting the result to View (which crashes on API level 16 cause there it returns a ViewRootImpl object which isn't an instance of View) I just use .getRootView() which returns a view already, so no casting required there.
Hope it helps someone :)
complete working example scrambled together from other stackoverflow posts, just copy-paste it, e.g., in the onClick listener of a button:
// inflate the layout of the popup window
LayoutInflater inflater = (LayoutInflater)getSystemService(LAYOUT_INFLATER_SERVICE);
if(inflater == null) {
return;
}
//View popupView = inflater.inflate(R.layout.my_popup_layout, null); // this version gives a warning cause it doesn't like null as argument for the viewRoot, c.f. https://stackoverflow.com/questions/24832497 and https://stackoverflow.com/questions/26404951
View popupView = View.inflate(MyParentActivity.this, R.layout.my_popup_layout, null);
// create the popup window
final PopupWindow popupWindow = new PopupWindow(popupView,
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT,
true // lets taps outside the popup also dismiss it
);
// do something with the stuff in your popup layout, e.g.:
//((TextView)popupView.findViewById(R.id.textview_popup_helloworld))
// .setText("hello stackoverflow");
// dismiss the popup window when touched
popupView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
popupWindow.dismiss();
return true;
}
});
// show the popup window
// which view you pass in doesn't matter, it is only used for the window token
popupWindow.showAtLocation(view, Gravity.CENTER, 0, 0);
//popupWindow.setOutsideTouchable(false); // doesn't seem to change anything for me
View container = popupWindow.getContentView().getRootView();
if(container != null) {
WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams p = (WindowManager.LayoutParams)container.getLayoutParams();
p.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND;
p.dimAmount = 0.3f;
if(wm != null) {
wm.updateViewLayout(container, p);
}
}
Since You are trying to pop up your dialog window by blurring the background screen, You must use this set of lines. You need to fetch the dialog attributes first, then set up some alpha values for the dialog attributes.
Now, your dialog with blur background is ready. But the important factor is to set a Flag FLAG_DIM_BEHIND for the window.
Now the result is yours. Hope it will helpful for someone...