Android PopupWindow处于活动状态时模糊或暗淡背景

k_d*_*day 77 android popupwindow android-popupwindow

当我使用弹出窗口显示时,我希望能够模糊或调暗背景popup.showAtLocation,并在popup.dismiss调用时将背景解开/调暗.

我曾尝试应用布局PARAMS FLAG_BLUR_BEHINDFLAG_DIM_BEHIND我的活动,但这似乎只是一旦我的应用程序开始模糊和朦胧的背景.

如何使用弹出框进行模糊/调光?

小智 105

问题是关于Popupwindow班级,但每个人都给出了使用Dialog班级的答案.如果你需要使用这个Popupwindow类,这几乎没用,因为Popupwindow没有getWindow()方法.

我找到了一个实际可行的解决方案Popupwindow.它只要求您用于后台活动的xml文件的根目录是FrameLayout.您可以为Framelayout元素android:foreground添加标记.此标记的作用是指定一个可绘制的资源,该资源将在整个活动之上分层(即,如果Framelayout是xml文件中的根元素).然后,您可以控制setAlpha()前景drawable 的不透明度().

您可以使用任何您喜欢的可绘制资源,但如果您只想要调暗效果,请在drawable文件夹中创建一个xml文件,<shape>标签为root.

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
    <solid android:color="#000000" />
</shape>
Run Code Online (Sandbox Code Playgroud)

(有关元素的更多信息,请参阅http://developer.android.com/guide/topics/resources/drawable-resource.html#Shapeshape).请注意,我没有在颜色标记中指定可使可绘制项目透明的alpha值(例如 #ff000000).原因是任何硬编码的alpha值似乎都会覆盖我们setAlpha()在代码中设置的任何新的alpha值,所以我们不希望这样.但是,这意味着可绘制项目最初将是不透明的(实心,不透明).所以我们需要在activity的onCreate()方法中使它透明.

这是Framelayout xml元素代码:

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/mainmenu"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:foreground="@drawable/shape_window_dim" >
...
... your activity's content
...
</FrameLayout>
Run Code Online (Sandbox Code Playgroud)

这是Activity的onCreate()方法:

public void onCreate( Bundle savedInstanceState)
{
  super.onCreate( savedInstanceState);

  setContentView( R.layout.activity_mainmenu);

  //
  // Your own Activity initialization code
  //

  layout_MainMenu = (FrameLayout) findViewById( R.id.mainmenu);
  layout_MainMenu.getForeground().setAlpha( 0);
}
Run Code Online (Sandbox Code Playgroud)

最后,调暗活动的代码:

layout_MainMenu.getForeground().setAlpha( 220); // dim

layout_MainMenu.getForeground().setAlpha( 0); // restore
Run Code Online (Sandbox Code Playgroud)

alpha值从0(不透明)变为255(不可见).当您关闭Popupwindow时,您应该取消调整活动.

我没有包含显示和解雇Popupwindow的代码,但这里有一个如何完成的链接:http://www.mobilemancer.com/2011/01/08/popup-window-in-android/

  • 有什么看法有Actionbar,你不能暗淡它 (2认同)

Mar*_*bey 69

由于PopupWindow只是增加了一个ViewWindowManager你可以使用updateViewLayout (View view, ViewGroup.LayoutParams params)更新LayoutParams您的PopupWindowcontentView调用演出后..().

设置窗口标志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);
Run Code Online (Sandbox Code Playgroud)

没有背景:

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);
Run Code Online (Sandbox Code Playgroud)

棉花糖更新:

On M PopupWindow将contentView包装在名为mDecorView的FrameLayout中.如果你深入了解PopupWindow源代码,你会发现类似的东西createDecorView(View contentView).mDecorView的主要目的是处理事件调度和内容转换,这是M的新功能.这意味着我们需要再添加一个.getParent()来访问容器.

使用背景需要更改以下内容:

View container = (View) popup.getContentView().getParent().getParent();
Run Code Online (Sandbox Code Playgroud)

API 18+的更好替代品

一个不太常见的解决方案ViewGroupOverlay:

1)获取所需的根布局

ViewGroup root = (ViewGroup) getWindow().getDecorView().getRootView();
Run Code Online (Sandbox Code Playgroud)

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();
}
Run Code Online (Sandbox Code Playgroud)

  • 这似乎不再适用于运行 Android 6.0 Marshmallow 的设备。layoutParams 不会转换为`WindowManager.LayoutParams`。有解决方法吗? (2认同)

小智 28

在你的xml文件中添加这样的宽度和高度为'match_parent'.

<RelativeLayout
        android:id="@+id/bac_dim_layout"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#C0000000"
        android:visibility="gone" >
</RelativeLayout>
Run Code Online (Sandbox Code Playgroud)

在你的活动中创建

//setting background dim when showing popup
back_dim_layout = (RelativeLayout) findViewById(R.id.share_bac_dim_layout);
Run Code Online (Sandbox Code Playgroud)

最后在显示弹出窗口时显示,并在退出弹出窗口时使其显示消失.

back_dim_layout.setVisibility(View.VISIBLE);
back_dim_layout.setVisibility(View.GONE);
Run Code Online (Sandbox Code Playgroud)

  • 但这不会使动作/工具栏变暗. (2认同)

Abh*_*ndi 11

另一个技巧是使用2个弹出窗口而不是一个.第一个弹出窗口将只是一个半透明背景的虚拟视图,提供暗淡效果.第二个弹出窗口是您想要的弹出窗口.

创建弹出窗口时的顺序: 显示虚拟弹出窗口1st,然后显示预期的弹出窗口.

破坏时的顺序: 关闭预期的弹出窗口,然后是虚拟弹出窗口.

链接这两个的最好方法是添加一个OnDismissListener并覆盖onDismiss()意图的方法来从它们的dimiss虚拟弹出窗口.

虚拟弹出窗口的代码:

fadepopup.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" 
    android:id="@+id/fadePopup"
    android:background="#AA000000">
</LinearLayout>
Run Code Online (Sandbox Code Playgroud)

显示淡入淡出弹出窗口以使背景变暗

private PopupWindow dimBackground() {

    LayoutInflater inflater = (LayoutInflater) EPGGRIDActivity.this
            .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
    final View layout = inflater.inflate(R.layout.fadepopup,
            (ViewGroup) findViewById(R.id.fadePopup));
    PopupWindow fadePopup = new PopupWindow(layout, windowWidth, windowHeight, false);
    fadePopup.showAtLocation(layout, Gravity.NO_GRAVITY, 0, 0);
    return fadePopup;
}
Run Code Online (Sandbox Code Playgroud)

  • @kenyee我找到了解决这个问题的方法.我首先显示'fade'弹出窗口,然后为了显示第二个弹出窗口我正在使用myFadePopup.getContentView().post(... myPopup.showAtLocation ...); (2认同)

PC.*_*PC. 5

我找到了解决方案

创建一个自定义透明对话框,在该对话框中打开弹出窗口:

dialog = new Dialog(context, android.R.style.Theme_Translucent_NoTitleBar);
emptyDialog = LayoutInflater.from(context).inflate(R.layout.empty, null);

/* blur background*/
WindowManager.LayoutParams lp = dialog.getWindow().getAttributes();  
lp.dimAmount=0.0f;  
dialog.getWindow().setAttributes(lp);  
dialog.getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND); 
dialog.setContentView(emptyDialog);
dialog.setCanceledOnTouchOutside(true);
dialog.setOnShowListener(new OnShowListener()
{
    @Override
    public void onShow(DialogInterface dialogIx)
    {
        mQuickAction.show(emptyDialog); //open the PopupWindow here
    }
});
dialog.show();
Run Code Online (Sandbox Code Playgroud)

对话框的xml(R.layout.empty):

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_height="match_parent" android:layout_width="match_parent"
     style="@android:style/Theme.Translucent.NoTitleBar" />
Run Code Online (Sandbox Code Playgroud)

现在你想在Popup窗口解散时关闭对话框.所以

mQuickAction.setOnDismissListener(new OnDismissListener()
{
    @Override
    public void onDismiss()
    {
        if(dialog!=null)
        {
            dialog.dismiss(); // dismiss the empty dialog when the PopupWindow closes
            dialog = null;
        }
    }
});
Run Code Online (Sandbox Code Playgroud)

注意:我在NewQuickAction这里使用插件来创建PopupWindow.它也可以在本机Popup Windows上完成


Mac*_*rse 0

你可以用android:theme="@android:style/Theme.Dialog"它来做到这一点。创建一个活动并将AndroidManifest.xml该活动定义为:

    <activity android:name=".activities.YourActivity"
              android:label="@string/your_activity_label"
              android:theme="@android:style/Theme.Dialog">
Run Code Online (Sandbox Code Playgroud)