Altura límite de ListView en Android

Quiero mostrar un botón debajo de un ListView . El problema es que si ListView se extiende (elementos agregados …), el botón se saca de la pantalla.

LinearLayout un LinearLayout con pesas (como se sugiere en Android: ¿por qué no hay maxHeight para una vista? ), Pero o bien obtuve los pesos incorrectos o simplemente no funcionó.

Además, encontré en algún lugar la pista para usar un RelativeLayout . El ListView se establecería encima del botón con el android:layout_above param.

El problema con esto es que no sé cómo colocar el botón después. En el ejemplo que encontré, la Vista debajo del ListView se ajustó usando android:layout_alignParentBottom , pero no quiero que mi botón se adhiera a la parte inferior de la pantalla.

¿Alguna idea aparte de usar setHeight-method y algunos cálculos del espacio requerido?


Editar: obtuve muchas respuestas útiles.

  • La solución de bigstone y user639183 casi funcionó a la perfección. Sin embargo, tuve que agregar un relleno extra / margen en la parte inferior del botón, ya que todavía se empujaría a mitad de la pantalla (pero luego se detuvo)

  • La respuesta de Adinia con el diseño relativo solo está bien si desea que el botón se fije en la parte inferior de la pantalla. No es lo que pretendía pero aún podría ser útil para otros.

  • La solución de AngeloS fue la que elegí al final, ya que acaba de crear los efectos que quería. Sin embargo, hice dos pequeños cambios en el LinearLayout alrededor del botón:

    • Primero, como no quería tener valores absolutos en mi diseño, cambié android:layout_height="45px" por wrap_content , que también funciona bien.

    • Segundo, como quería que el botón se centrara horizontalmente, lo cual solo es compatible con LinearLayout vertical, cambié android: orientation = “horizontal” a “vertical”.

    AngeloS también declaró en su publicación inicial que no estaba seguro de si el android:layout_weight="0.1" en el LinearLayout alrededor del ListView tuvo algún efecto; ¡Lo intenté y realmente lo hace! Sin, el botón sale de la pantalla de nuevo.

Tuve este problema exacto y para resolverlo creé dos LinearLayouts separados para alojar el ListView y el Button respectivamente. A partir de ahí puse ambos en otro Linear Layout y establecí la android:orientation ese contenedor en android:orientation vertical . También establecí el peso del LinearLayout que contenía el ListView en 0.1 pero no sé si eso tiene algún efecto. Desde allí, puede establecer la altura del contenedor inferior (que tiene su botón) a la altura que desee.

EDITAR esto es lo que quiero decir:

          

La solución anterior fijará el botón en la parte inferior de la pantalla.


Para que el botón flote en la parte inferior de la lista, cambie la altura de ListView01 a wrap_content :

          

Resolví este problema en el código, estableciendo la altura de la vista de lista solo si tiene más de 5 elementos:

 if(adapter.getCount() > 5){ View item = adapter.getView(0, null, listView); item.measure(0, 0); ViewGroup.LayoutParams params = new ViewGroup.LayoutParams(LayoutParams.MATCH_PARENT, (int) (5.5 * item.getMeasuredHeight())); listView.setLayoutParams(params); } 

Tenga en cuenta que establezco la altura máxima en 5,5 veces la altura de un solo elemento, por lo que el usuario sabrá con seguridad que hay algo de desplazamiento que hacer. 🙂

En su última edición, solo tiene que agregar android:layout_above="@+id/butt1" en su código ListView.

Y para mostrarle (y a todos los que aquí trataron una respuesta anterior) que realmente no necesita usar más de un RelativeLayout , aquí está su código corregido :

          

y el resultado , usando una lista aleatoria:
enter image description here

Con LinearLayout , establezca la altura de su ListView y Button en wrap_content y agregue un peso = 1 a ListView . Esto debería funcionar como lo desees.
Y sí, establezca el layout_gravity del Button en la bottom

RelativeLayout es una solución, si no desea que el botón se quede demasiado cerca de la parte inferior, puede agregar márgenes (rellenar un botón lo rompería porque usa un fondo de 9 parches y establece su propio relleno).

Sería lo mismo si utilizara LinearLayout : la manera de lograr lo que desea es establecer ListView en una altura = 0 y weight = 1, y para la altura del botón = wrap_content y weight = 0. (establecer ambos en wrap_content, como dijo user639183, no limitaría la altura de ListView ).

Encontré una forma de hacerlo sin usar contenedores nesteds, inspirados en la solución de AngeloS.

LinearLayout con orientación vertical, que tiene un ListView y un botón. Configuro el android:layout_weight="0.1" para el ListView .

Logra que el botón permanezca siempre al final de la lista. Y el botón no se desplaza de la pantalla cuando la lista crece.

   

Probablemente puedas hacer que esto funcione usando contenedores nesteds. Es posible que deba envolver el Botón en un segundo contenedor (interno) para que ocupe más espacio, y simplemente alinee el Botón en la parte superior del contenedor interno.

Posible algo como esto:

Disposición relativa

— Vista de la lista

— Disposición relativa

—- Botón

Usando las diferentes opciones de alineación en los dos contenedores, debería poder hacer que esto funcione.

Esta es la forma más limpia de hacerlo:

        

Es similar a la solución de Angelos, pero no necesita la distribución lineal que envuelve ListView. También puede usar un FrameLayout que es más liviano que un LinearLayout para cerrar el Botón.

La idea se resume en las muy buenas soluciones por:

  • AngeloS
  • Brillar

Ambos parecen funcionar perfectamente al menos en v4.4.3.

Todavía tuve que dedicar algo de tiempo a escribir el código de prueba para verificarlo y confirmar cada método. A continuación se muestra el código de prueba mínimo autónomo requerido.


El diseño se basa en la solución de Sparkle, ya que contiene menos diseño nested. También se ha actualizado para reflejar las comprobaciones actuales de LINT.

     

La actividad proporciona el código repetitivo para probar la solución por ti mismo.

 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); final ListView listview = (ListView)findViewById(R.id.listview); final ArrayAdapter adapter = new ArrayAdapter(this, android.R.layout.simple_list_item_1, new ArrayList()); adapter.setNotifyOnChange(true); listview.setAdapter(adapter); findViewById(R.id.btn).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { int count = adapter.getCount(); adapter.add(String.valueOf(count)); listview.setSelection(count); } }); } } 

Siéntase libre de agregar o mejorar, ya que se trata de “wiki de la comunidad”.

Intenta usar RelativeLayout con el botón en la parte inferior. Establezca la altura del diseño como “wrap_content”. No lo he intentado. Solo idea

en LinearLayout, simplemente agrega android:layout_weight="1" para ti ListView

Lo siguiente fue lo que funcionó para mí …

  if(adapter.getCount() > 3){ View item = adapter.getView(0, null, impDateListView); item.measure(0, 0); LayoutParams params = impDateListView.getLayoutParams(); params.width = LayoutParams.MATCH_PARENT; params.height = 3 * item.getMeasuredHeight(); impDateListView.setLayoutParams(params); } 

Nota: Params.width = … Necesita establecerse también …

El ejemplo anterior es cuando usa TableRow y ListView dentro de TableRow …

envolver contenido en diseño lineal

en la vista de lista agregar: android: layout_weight = “1”

en su botón establece altura fija

      

Si desea que el contenido debajo de la vista de lista se mueva hacia abajo a medida que los elementos se agregan a la lista, intente con esta solución:

Agregue relleno positivo en la parte inferior de la vista de lista y relleno negativo en la parte superior del “pie de página”. Esto funcionará en un diseño lineal o un diseño relativo.

   

Como no hay ningún atributo MaxHeight, la mejor opción es establecer la altura del ListView en un valor establecido o usar wrap_content .

Lo resolví poniendo ListView dentro de ScrollView. A Lint no le gustó, pero al agregar un minHeight y configurar el fillViewport en verdadero, tengo un buen resultado.