当Android PopupWindow激活时模糊或昏暗的背景
当我使用popup.showAtLocation
显示popup窗口时,我希望能够使背景变模糊或变暗,并在调用popup.dismiss时解除/调暗背景。
我已经尝试应用布局参数FLAG_BLUR_BEHIND
和FLAG_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
只是添加一个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);
棉花糖更新:
在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);
- PreferenceFragment是否故意从兼容性软件包中排除?
- Android:java.lang.OutOfMemoryError:未能分配一个23970828字节分配,其中包含2097152个空闲字节和2MB,直到OOM
- 错误膨胀类android.support.design.widget.NavigationView
- Android上的SQLite的最佳做法是什么?
- 以编程方式滑动时更改ViewPageranimation持续时间
- 使用Android和SQLite从数据库获取布尔值
- 未能加载广告:3
- build立设备进行开发(??????没有权限)
- Android“gps需要ACCESS_FINE_LOCATION”错误,即使我的清单文件包含这个