PopupWindow fuera de la pantalla cuando el tamaño no se especifica

La mayoría de los ejemplos por ahí especifican exactamente el ancho y la altura de la ventana emergente. Quiero que sean WRAP_CONTENT – ya que el contenido está dinámicamente determinado, por lo que en el constructor establezco -2 para el ancho y la altura y lo muestro a través de showAsDropDown (View anchor)

Haciendo esto, el popup siempre se dibuja debajo de la vista de anclaje, lo que significa que puede ser extraído de la pantalla. El fragmento siguiente muestra el problema. Pruebe a hacer clic en el último TextView y no verá ningún PopupWindow, ya que se muestra fuera de los límites de Windows. ¿Por qué no funciona? Observo que especificar la dimensión explícitamente (por ejemplo, 200, 100) no desencadena el problema. Inténtalo tú mismo

package com.zybnet.example.popupdemo; import android.app.Activity; import android.graphics.Color; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; import android.widget.LinearLayout; import android.widget.PopupWindow; import android.widget.TextView; public class PopupDemoActivity extends Activity implements OnClickListener { private PopupWindow popup; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // -2 means WRAP_CONTENT THIS TRIGGERS THE PROBLEM popup = new PopupWindow(getPopupContent(), -2, -2); // When you specify the dimensions everything goes fine //popup = new PopupWindow(getPopupContent(), 200, 100); LinearLayout layout = new LinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); // FILL_PARENT and same layout weight for all children LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(-1, -1, 1); for (int i = 0; i < 10; i++) { TextView tv = new TextView(this); tv.setText("Click to show popup"); tv.setOnClickListener(this); layout.addView(tv, params); } setContentView(layout); } @Override public void onClick(View view) { popup.dismiss(); popup.showAsDropDown(view); } private View getPopupContent() { TextView popupContent = new TextView(this); popupContent.setText("Some text here"); popupContent.setTextColor(Color.parseColor("#5000ae")); popupContent.setBackgroundColor(Color.parseColor("#ff00ff")); popupContent.setPadding(10, 20, 20, 10); return popupContent; } } 

Estoy empezando a dudar que en el contexto de un PopupWindow que -2, -2 realmente significa WRAP_CONTENT más bien creo que su interpretación es como width = -2 height = -2

Esto es de la fuente de Android

 public PopupWindow(View contentView, int width, int height, boolean focusable) { if (contentView != null) { mContext = contentView.getContext(); mWindowManager = (WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE); } setContentView(contentView); setWidth(width); setHeight(height); setFocusable(focusable); } 

Donde setWidth(int width) es sólo un simple mWidth = width; Creo que lo que estás buscando es el método setWindowLayoutMode (int widthSpec, int heightSpec) . Ahí es donde debe pasar en el WRAP_CONTENT

Si todo lo demás falla, mida el ancho y la altura del TextView y luego use setWidth y setHeight como se esperaba.

Editar :

Sólo lo probé por mí mismo y agregó esta línea de código para que funcione

  // -2 means WRAP_CONTENT THIS TRIGGERS THE PROBLEM popup = new PopupWindow(getPopupContent(), 200, 100); popup.setWindowLayoutMode(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); // When you specify the dimensions everything goes fine //popup = new PopupWindow(getPopupContent(), 200, 100); LinearLayout layout = new LinearLayout(this); layout.setOrientation(LinearLayout.VERTICAL); 

Dejé los comentarios originales allí para que usted pueda ver por ti mismo donde todo debe ir.

Edit 2: Bueno, así que tomé el código que publicó y lo probé literalmente en mi dispositivo, y tenía razón, no funcionó porque cuando Android está determinando qué vistas de diseño para ponerlo, se basa en el ancho y Altura que usted proporcionó. Lo que significa que ya que está utilizando 0 y 0 como su ancho y alto, Android llegará y decir, "Oh mira, la caja es sólo un 0 por 0 cuadro para que pueda mostrarlo como un popup por debajo del contenido". Esto no es lo que se desea sin embargo! La cosa es, usted sabe que la caja va a ser más grande que eso, así que deja comenzar a poner en algunos números diferentes y ver los resultados que vienen de él.

 popup = new PopupWindow(getPopupContent(), 1, 1); 

Ahora, cuando vaya y haga clic en el cuadro inferior, observe que salta por encima. Eso es porque Android SABE que el ancho y la altura son 1 (como he establecido en el constructor) y que el espacio de pantalla disponible debajo del elemento de lista es 0. Bueno, si no hay suficiente espacio para mostrarlo allí, entonces lo Debe por encima de entonces!

Introduzca aquí la descripción de la imagen

¡Pero espera! ¿Qué pasa si como en mi ejemplo actual la cadena agrega más contenido cada vez? Bueno, aquí es donde las cosas se ponen interesantes. Ya ves, en mi siguiente captura de pantalla que la ventana emergente, aunque debería ser mostrada ya que es de 6 líneas de largo ahora, es más bien se muestra en la parte inferior! Oh mierda, cierto! Eso es porque está midiendo contra el 1 1 que utilicé en el constructor. Bueno, ¿cuáles son algunas soluciones a esto entonces?

Introduzca aquí la descripción de la imagen

Solución 1: Mi manera preferida sería tomar una conjetura en cuál sería la altura máxima media del TextView y después lanzar simplemente en un genérico número grande.

 popup = new PopupWindow(getPopupContent(), 300, 300); //just guessing it won't get bigger than that 

Solución Dos: Esto es más apropiado, pero usted está sacrificando un poco de velocidad para hacerlo. Utilizar la clase Paint para medir el tamaño del contenido de texto y pasarlo a la setWidth() y setHeight() antes de mostrar la ventana emergente. Seguí adelante y construí una solución casi completa, pero no midí en relleno y cosas (ver el comentario)

 private int maxWidth; private int maxHeight; private Paint p = new Paint(); private Rect bounds = new Rect(); private View getPopupContent() { maxWidth = 0; maxHeight = 0; TextView popupContent = new TextView(this); popupContent.setText(popupText += "\n" + DEMO); popupContent.setTextColor(Color.parseColor("#5000ae")); popupContent.setBackgroundColor(Color.parseColor("#ff00ff")); popupContent.setPadding(10, 20, 20, 10); //the measure can only work line by line so I split it up by line String[] temp = popupText.split("\n"); for (String s : temp){ //measure each line of string and get its width and height p.getTextBounds(s, 0, s.length(), bounds); //keep a running total of the longest width maxWidth = (bounds.width() > maxWidth) ? bounds.width() : maxWidth; //add up each of the heights maxHeight += bounds.height(); } //also take in account the padding too... if you REALLY want it to be completely robust //probably adding another 20 or 30 to the maxHeight should be good return popupContent; } 

Y luego en el onClick() agregué estas dos líneas

  popup.setHeight(maxHeight); popup.setWidth(maxWidth); 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.