由于PopupWindow 只是将View 添加到WindowManager,您可以在调用show..() 后使用updateViewLayout (View view, ViewGroup.LayoutParams params) 更新PopupWindow 的contentView 的LayoutParams。
设置窗口标志FLAG_DIM_BEHIND 将使窗口后面的所有内容变暗。使用dimAmount 控制暗淡量(1.0 表示完全不透明,0.0 表示没有暗淡)。
请记住,如果您为 PopupWindow 设置背景,它会将您的 contentView 放入容器中,这意味着您需要更新它的父级。
有背景:
PopupWindow popup = new PopupWindow(contentView, width, height);
popup.setBackgroundDrawable(background);
popup.showAsDropDown(anchor);
View container = (View) popup.getContentView().getParent();
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams p = (WindowManager.LayoutParams) container.getLayoutParams();
// add flag
p.flags |= WindowManager.LayoutParams.FLAG_DIM_BEHIND;
p.dimAmount = 0.3f;
wm.updateViewLayout(container, p);
无背景:
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);
棉花糖更新:
On M PopupWindow 将 contentView 包装在名为 mDecorView 的 FrameLayout 中。如果您深入研究 PopupWindow 源代码,您会发现类似 createDecorView(View contentView) 的内容。mDecorView 的主要目的是处理事件调度和内容转换,这对 M 来说是新的。这意味着我们需要再添加一个 .getParent() 来访问容器。
背景需要更改为:
View container = (View) popup.getContentView().getParent().getParent();
API 18+ 的更好替代方案
使用ViewGroupOverlay 的一个不那么老套的解决方案:
1) 获取所需的根布局
ViewGroup root = (ViewGroup) getWindow().getDecorView().getRootView();
2) 致电applyDim(root, 0.5f); 或clearDim()
public static void applyDim(@NonNull ViewGroup parent, float dimAmount){
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);
}
public static void clearDim(@NonNull ViewGroup parent) {
ViewGroupOverlay overlay = parent.getOverlay();
overlay.clear();
}