Desenfoque o fondo oscuro cuando Android PopupWindow está activo

Me gustaría poder desenfocar o atenuar el fondo cuando muestro mi ventana emergente usando popup.showAtLocation , y unblur / dim el fondo cuando se llama popup.dismiss .

He intentado aplicar los parámetros de diseño FLAG_BLUR_BEHIND y FLAG_DIM_BEHIND a mi actividad, pero esto parece borrar y atenuar el fondo tan pronto se inicie mi aplicación.

¿Cómo puedo hacer borrosidad / atenuación sólo con pop-ups?

La pregunta era acerca de la clase Popupwindow , sin embargo, todos han dado respuestas que utilizan la clase Dialog . Eso es bastante inútil si necesita usar la clase Popupwindow , porque Popupwindow no tiene un método getWindow() .

He encontrado una solución que realmente funciona con Popupwindow . Sólo requiere que la raíz del archivo xml que utilice para la actividad de fondo sea FrameLayout . Puedes darle al elemento Framelayout un android:foreground etiqueta de android:foreground . Lo que hace esta etiqueta es especificar un recurso dibujable que se superpondrá en la parte superior de toda la actividad (es decir, si Framelayout es el elemento raíz en el archivo xml). A continuación, puede controlar la opacidad ( setAlpha() ) del primer plano dibujable.

Puede utilizar cualquier recurso extraíble que desee, pero si sólo desea un efecto de atenuación, cree un archivo xml en la carpeta dibujable con la etiqueta <shape> como 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> 

(Consulte http://developer.android.com/guide/topics/resources/drawable-resource.html#Shape para obtener más información sobre el elemento de shape ). Tenga en cuenta que no especificé un valor alfa en la etiqueta de color que haría transparente el elemento #ff000000 (por ejemplo, #ff000000 ). La razón de esto es que cualquier valor alfanumérico codificado parece anular cualquier nuevo valor alfa que establezcamos a través de setAlpha() en nuestro código, por lo que no queremos eso. Sin embargo, esto significa que el elemento estirable será inicialmente opaco (sólido, no transparente). Así que tenemos que hacerlo transparente en el método onCreate() la actividad.

Aquí está el código del elemento xml de Framelayout:

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

Aquí está el método onCreate () de la actividad:

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

Finalmente, el código para atenuar la actividad:

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

Los valores alfa van de 0 (opaco) a 255 (invisible). Usted debe desmarque la actividad cuando usted rechaza el Popupwindow.

No he incluido código para mostrar y despedir el Popupwindow, pero aquí hay un enlace a cómo se puede hacer: http://www.mobilemancer.com/2011/01/08/popup-window-in-android/

Debido a que PopupWindow sólo agrega una View a WindowManager , puede usar updateViewLayout (View view, ViewGroup.LayoutParams params) para actualizar los LayoutParams del LayoutParams de su contentView después de llamar a show .. ().

Si se establece el indicador de ventana FLAG_DIM_BEHIND obtendrá todo detrás de la ventana. Utilice dimAmount para controlar la cantidad de atenuación (1,0 para completamente opaco a 0,0 para no oscurecer).

Tenga en cuenta que si establece un fondo para su PopupWindow pondrá su contentView en un contenedor, lo que significa que necesita actualizar su padre.

Con antecedentes:

 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(); p.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND; p.dimAmount = 0.3f; wm.updateViewLayout(container, p); 

Sin antecedentes:

 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(); p.flags = WindowManager.LayoutParams.FLAG_DIM_BEHIND; p.dimAmount = 0.3f; wm.updateViewLayout(contentView, p); 

Actualización de Marshmallow:

En M PopupWindow envuelve el contentView dentro de un FrameLayout llamado mDecorView. Si busca en la fuente de PopupWindow, encontrará algo como createDecorView(View contentView) . El objetivo principal de mDecorView es gestionar el envío de sucesos y las transiciones de contenido, que son nuevas para M. Esto significa que necesitamos agregar una más .getParent () Para acceder al contenedor.

Con el fondo que requeriría un cambio a algo como:

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

Mejor alternativa para API 18+

Una solución menos hacky con ViewGroupOverlay :

1) Conseguir un asimiento de la disposición de la raíz deseada

 ViewGroup root = (ViewGroup) getWindow().getDecorView().getRootView(); 

2) Llame a applyDim(root, 0.5f); O 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(); } 

En su archivo xml agregue algo como esto con el ancho y la altura como '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> 

En su actividad encrear

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

Finalmente hacer visible cuando se muestra su ventana emergente y hacer su visible ido cuando sale popupwindow.

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

Otro truco es usar 2 ventanas emergentes en lugar de una. La primera ventana emergente será simplemente una vista falsa con el fondo translúcido que proporciona el efecto dévil. La segunda ventana emergente es la ventana emergente deseada.

Secuencia durante la creación de ventanas emergentes: Muestre la ventana emergente 1 y luego la ventana emergente deseada.

Secuencia durante la destrucción: Deseche la ventana emergente deseada y luego la ventana emergente de muñeca.

La mejor manera de vincular estos dos es agregar un OnDismissListener y anular el método onDismiss() de la intención de dimiss la ventana emergente dummy de su.

Código para la ventana emergente ficticia:

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> 

Mostrar desvanecimiento emergente para atenuar el fondo

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

He encontrado una solución para esto

Crear un cuadro de diálogo transparente personalizado y dentro de ese cuadro de diálogo abrir la ventana emergente:

 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 para el diálogo (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" /> 

Ahora desea descartar el diálogo cuando se desactiva la ventana emergente. asi que

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

Nota: He utilizado el complemento NewQuickAction para crear PopupWindow aquí. También se puede hacer en las ventanas emergentes nativas

Puedes usar android:theme="@android:style/Theme.Dialog" para hacer eso. Crea una actividad y en tu AndroidManifest.xml define la actividad como:

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

Este código funciona

  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); 
  • Android: agrega la vista al diseño haciendo que el diseño esté delante de ActionBar
  • No se puede interactuar con PopupWindow y Background (GoogleMap)
  • Android PopupWindow se oculta detrás de los botones de navegación en Nexus 5
  • Cuándo utilizar Android PopupWindow vs Dialog
  • PopupWindow en una coordenada específica sin vista de anclaje
  • El fondo de PopupWindow a veces se vuelve transparente y morado
  • PopupWindow - no funciona en algunos dispositivos
  • Android: Ventana emergente: Se ha intentado finalizar un evento de entrada pero el receptor de eventos de entrada ya se ha eliminado
  • Android: setText () para TextView en PopupWindow no funciona
  • Android Nougat PopupWindow showAsDropDown (...) La gravedad no funciona
  • Cómo definir el diseño en un PopupWindow de un archivo xml, cuando el método PopupWindow se llama desde una clase independiente
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.