Desenfoque o fondo oscuro cuando Android PopupWindow activo

Me gustaría poder difuminar o atenuar el fondo cuando muestro mi ventana emergente usando popup.showAtLocation , y desdibujo / atenúo el fondo cuando se llama a popup.dismiss .

Intenté aplicar los parámetros de diseño FLAG_BLUR_BEHIND y FLAG_DIM_BEHIND a mi actividad, pero parece que esto FLAG_DIM_BEHIND y atenúa el fondo tan pronto como se inicia mi aplicación.

¿Cómo puedo hacer blur / dimming solo con ventanas emergentes?

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

Encontré una solución que realmente funciona con Popupwindow . Solo requiere que la raíz del archivo xml que utilice para la actividad de fondo sea FrameLayout . Puedes darle al elemento Framelayout una etiqueta android:foreground . Lo que hace esta etiqueta es especificar un recurso dibujable que se superpondrá a 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 usar cualquier recurso dibujable que desee, pero si solo desea un efecto de atenuación, cree un archivo xml en la carpeta dibujable con la etiqueta como raíz.

     

(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 especifique un valor alfa en la etiqueta de color que haría que el elemento #ff000000 transparente (por ejemplo, #ff000000 ). La razón de esto es que cualquier valor alfa codificado parece anular cualquier valor alfa nuevo que establezcamos a través de setAlpha() en nuestro código, por lo que no queremos eso. Sin embargo, eso significa que el elemento dibujable será inicialmente opaco (sólido, no transparente). Entonces, debemos hacerlo transparente en el método onCreate() la actividad.

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

  ... ... your activity's content ...  

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); // restre 

Los valores alfa van de 0 (opaco) a 255 (invisible). Debe desactivar la actividad cuando cierre la Ventana emergente.

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

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

Configurar el indicador de ventana FLAG_DIM_BEHIND todo detrás de la ventana. Use dimAmount para controlar la cantidad de dim (1.0 para completamente opaco a 0.0 para no dim).

Tenga en cuenta que si establece un fondo en su PopupWindow , pondrá su contentView en un contenedor, lo que significa que debe actualizar su contentView principal.

Con el fondo:

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

Sin fondo:

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

Actualización de Marshmallow:

En M PopupWindow envuelve el contentView dentro de un FrameLayout llamado mDecorView. Si profundiza en el origen de PopupWindow, encontrará algo como createDecorView(View contentView) . El objective principal de mDecorView es gestionar el envío de eventos y las transiciones de contenido, que son nuevos para M. Esto significa que necesitamos agregar uno más .getParent () para acceder al contenedor.

Con antecedentes que requerirían un cambio a algo como:

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

Mejor alternativa para API 18+

Una solución menos hacky usando ViewGroupOverlay :

1) Obtener un control del diseño de raíz deseado

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

2) Llamar 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 ancho y alto como ‘match_parent’.

   

En tu actividad oncreate

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

Finalmente haz visible cuando muestres tu ventana emergente y la hagas desaparecer cuando salgas de la ventana emergente.

 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 ficticia con fondo translúcido que proporciona el efecto tenue. La segunda ventana emergente es su ventana emergente prevista.

Secuencia al crear ventanas emergentes: muestre la ventana emergente ficticia primero y luego la ventana emergente deseada.

Secuencia al destruir: Descarta la ventana emergente deseada y luego la ventana emergente ficticia.

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

Código para la ventana emergente ficticia:

fadepopup.xml

    

Mostrar ventana emergente de fundido 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; } 

Encontré una solución para esto

Cree un diálogo transparente personalizado y dentro de ese cuadro de diálogo abra 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):

   

ahora desea descartar el diálogo cuando se cierra 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 usado el complemento NewQuickAction para crear PopupWindow aquí. También se puede hacer en 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:

   

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