我可以使用 PopupWindow 而非 Dialog 来调暗背景吗?我之所以这样问是因为我正在使用 Dialogs,但是 Dialog 不会显示在点击的项目下方,而使用 PopupWindow,弹出窗口已经在项目下方显示了。
我可以使用 PopupWindow 而非 Dialog 来调暗背景吗?我之所以这样问是因为我正在使用 Dialogs,但是 Dialog 不会显示在点击的项目下方,而使用 PopupWindow,弹出窗口已经在项目下方显示了。
我使用以下代码,并且它对我很有效。
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);
}
来自这个回答。
更新:
fdermishin在下方的回答更好。我已经将其向后测试到API级别19,并且它运行良好。
如果您正在使用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()
看起来我找到了如何摆脱API版本检查的方法。使用container = popupWindow.getContentView().getRootView()
解决了这个问题,但我还没有为旧的API进行测试。根据曹俊岳的解决方案进行调整:
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);
}
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);
}
我发布了一个新答案,因为我无法在JiaJiaGu的答案上进行评论。
com.android.launcher3 W/OpenGLRenderer: Incorrectly called buildLayer on View: ShortcutAndWidgetContainer, destroying layer...
。总之,这段代码让我感到不舒服,那个硬编码的getParent()
的变量数量看起来并不是很具有未来可靠性。 - HughHughTeotl