当Android PopupWindow激活时模糊或昏暗的背景

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

我已经尝试应用布局参数FLAG_BLUR_BEHINDFLAG_DIM_BEHIND到我的活动,但这似乎只是模糊和昏暗的背景,尽快我的应用程序启动。

我怎样才能使popup窗口模糊/调光?

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

我发现一个实际上与Popupwindow一起使用的解决scheme。 它只需要你用于后台活动的xml文件的根就是一个FrameLayout 。 你可以给Framelayout元素一个android:foreground标签。 这个标签做的是指定一个可绘制的资源,它将被分层到整个活动之上(也就是说,如果Framelayout是xml文件中的根元素)。 然后,您可以控制可绘制前景的不透明度( setAlpha() )。

你可以使用你喜欢的任何可绘制的资源,但是如果你只是想要一个调光效果,创build一个xml文件的可绘制文件夹中的<shape>标签作为根。

 <?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> 

(有关shape元素的更多信息,请参阅http://developer.android.com/guide/topics/resources/drawable-resource.html#Shape )。 请注意,我没有在颜色标签中指定一个透明的可绘制项目的alpha值(例如#ff000000 )。 原因是任何硬编码的alpha值似乎都会覆盖我们通过setAlpha()在我们的代码中设置的任何新的alpha值,所以我们不希望这样做。 但是,这意味着可绘制的项目最初将是不透明的(实体的,不透明的)。 所以我们需要在活动的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> 

这里是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); } 

最后,调暗活动的代码:

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

alpha值从0 (不透明)到255 (不可见)。 当您解散Popupwindow时,您应该取消调暗活动。

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

由于PopupWindow只是添加一个ViewWindowManager你可以在调用show ..()后使用updateViewLayout (View view, ViewGroup.LayoutParams params)来更新PopupWindowcontentViewLayoutParams

设置窗口标志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); 

棉花糖更新:

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

随着背景,将需要改变的东西,如:

 View container = (View) popup.getContentView().getParent().getParent(); 

API 18+更好的select

使用ViewGroupOverlay更简单的解决scheme:

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(); } 

在你的xml文件中join类似于“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> 

在你的活动中创build

 //setting background dim when showing popup back_dim_layout = (RelativeLayout) findViewById(R.id.share_bac_dim_layout); 

最后,当你显示你的popupwindow,并在退出popupwindow时使它看起来不见了,就可以看到它了。

 back_dim_layout.setVisibility(View.VISIBLE); back_dim_layout.setVisibility(View.GONE); 

另一个诀窍是使用2个popup窗口而不是一个。 第一个popup窗口只是一个带有半透明背景的虚拟视图,提供了暗淡的效果。 第二个popup窗口是您想要的popup窗口。

创buildpopup窗口时的顺序:显示虚拟popup窗口1st,然后显示预期的popup窗口。

破坏时的顺序:closurespopup的窗口,然后popup虚拟popup窗口。

链接这两个方法的最好方法是添加一个OnDismissListener,并覆盖onDismiss()方法来打开它们的虚拟popup窗口。

代码为虚拟popup窗口:

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> 

显示淡入淡出以调暗背景

 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; } 

我find了一个解决scheme

创build一个自定义透明对话框,并在该对话框中打开popup窗口:

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

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" /> 

现在你想在popup窗口closures时closures对话框。 所以

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

注意:我在这里使用了NewQuickAction插件来创buildPopupWindow。 它也可以在本地popup窗口上完成

你可以使用android:theme="@android:style/Theme.Dialog"来做到这一点。 创build一个活动,并在您的AndroidManifest.xml中将活动定义为:

  <activity android:name=".activities.YourActivity" android:label="@string/your_activity_label" android:theme="@android:style/Theme.Dialog"> 

此代码工作

  pwindo = new PopupWindow(layout, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT, true); pwindo.showAtLocation(layout, Gravity.CENTER, 0, 0); pwindo.setOutsideTouchable(false); View container = (View) pwindo.getContentView().getParent(); 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; wm.updateViewLayout(container, p);