ListView empuja otras vistas fuera de la pantalla

Estoy luchando para obtener un diseño de aspecto correctamente, y he tratado de producir el más corto, el menor ejemplo posible de mi problema.

Mi objetivo es tener una vista de cabecera y pie de página, en la parte superior e inferior de la pantalla, con un ListView entre los dos, con otra vista (llamémosla etiqueta , es el cuadro gris de las capturas de pantalla) directamente debajo de la ListView . Esta etiqueta y el pie de página siempre deben mostrarse cuando ListView necesita desplazarse.

Resultado visual

Cuando el ListView no necesita desplazarse (esto es correcto):

Cuando el ListView no necesita desplazarse

Cuando el ListView necesita desplazarse, el pie de página y el cuadro gris se alejan de la pantalla (incorrecto):

Cuando el ListView necesita desplazarse

Diseño

 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="header" android:padding="20dp" android:textSize="18sp" android:background="@color/red"/> <ListView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@android:id/list" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="this should be directly below the ListView, but not pushed off screen when the ListView needs to scroll" android:padding="5dp" android:background="@color/light_gray" android:textColor="@color/black"/> <!-- Used to push the footer to the bottom --> <View android:layout_width="0dp" android:layout_height="0dp" android:layout_weight="1"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="footer" android:padding="20dp" android:textSize="18sp" android:background="@color/blue"/> </LinearLayout> 

Actividad de prueba

 public class TestActivity extends ListActivity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ArrayList<String> items = new ArrayList<String>(); items.add("one"); items.add("two"); items.add("three"); items.add("four"); items.add("five"); items.add("six"); items.add("seven"); items.add("eight"); items.add("nine"); items.add("ten"); setListAdapter(new ArrayAdapter<String>(this, R.layout.simple_list_item_1, items)); setContentView(com.myproject.android.R.layout.test); } } 

He intentado algunos enfoques diferentes, como dar el layout_weight="1" ListView layout_weight="1" y quitar la View blanco que uso para empujar el pie de página a la parte inferior. Esto es casi lo que quiero, mantiene el pie de página y la etiqueta visible cuando el ListView desplaza, pero cuando sólo tiene 1 o 2 elementos, necesito el cuadro gris justo debajo del ListView . También he intentado usar un RelativeLayout , sin éxito. Supongo que entiendo mal las cosas.

EDITAR

Aquí está mi intento con un RelativeLayout que todavía no es correcto.

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="header" android:padding="20dp" android:textSize="18sp" android:background="@color/red" android:id="@+id/header" /> <ListView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@android:id/list" android:layout_below="@id/header"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="this should be directly below the ListView, but not pushed off screen when the ListView needs to scroll" android:padding="5dp" android:background="@color/light_gray" android:textColor="@color/black" android:layout_below="@android:id/list"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="footer" android:padding="20dp" android:textSize="18sp" android:background="@color/blue" android:layout_alignParentBottom="true" android:id="@+id/footer"/> </RelativeLayout> 

Diseño relativo (aún incorrecto):

Intento de diseño relativo

Añadir android:layout_weight="1" a la lista. Eso hará que sea el elemento más grande en el LinearLayout, sin empujar a los otros fuera de la pantalla.

Este diseño agrega el encabezado en la parte superior de la pantalla y el pie de página y el fondo. La lista llena el resto de la pantalla. Con estas tesis, los elementos de la lista nunca quedan oscurecidos por el pie de página. Vea cómo agregar el cuadro gris debajo del XML …

 <?xml version="1.0" encoding="utf-8"?> <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="header" android:padding="20dp" android:textSize="18sp" android:background="@color/red" android:id="@+id/header" /> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="footer" android:padding="20dp" android:textSize="18sp" android:background="@color/blue" android:layout_alignParentBottom="true" android:id="@+id/footer"/> <ListView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@android:id/list" android:layout_below="@id/header" android:layout_above="@id/footer"/> </RelativeLayout> 

De acuerdo. Este XML resuelve el problema del pie de página que falta. Ahora tenemos que añadir un cuadro gris al final de la lista. Creo que hay dos maneras de hacerlo:

Una solución que implementé y encontré útil fue mantener el listview dentro de un diseño lineal con altura fija para que no se extienda ni se superponga a otros elementos.

Algo como esto:

 <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="header" android:padding="20dp" android:textSize="18sp" android:background="@color/red" android:id="@+id/header" /> <LinearLayout android:layout_width="fill_parent" android:layout_height="150dip" //assume 150dip height is sufficient <ListView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="@android:id/list" android:layout_below="@id/header"/> </LinearLayout> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="this should be directly below the ListView, but not pushed off screen when the ListView needs to scroll" android:padding="5dp" android:background="@color/light_gray" android:textColor="@color/black" android:layout_below="@android:id/list"/> 

Dos años tarde para responder a la pregunta, pero voy a dejar mi solución para que pueda ayudar a alguien con el mismo problema. Resuelvo este problema usando 2 LinearLayouts anidados y usando layout_weigth. Tal vez no sea el mejor diseño performatico, pero alcanza el efecto deseado.

Debe organizar su diseño de esta manera:

  1. Su ListView tendrá wrap_content altura para tomar sólo el espacio necesario cuando no llenar toda la pantalla.
  2. Tu ListView estará dentro de un diseño con altura usando layout_weight para que la lista solo tome el espacio necesario cuando no llene toda la pantalla y tome sólo un espacio limitado de la pantalla cuando tenga tamaño enouth para empujar las vistas fuera de la pantalla.
  3. La vista del cuadro gris que debe estar inmediatamente debajo de la lista tendrá una altura de wrap_content y será un sinbling del diseño del paso 2.
  4. Este diseño y la caja gris estarán dentro de un segundo diseño con la altura de wrap_content para que puedan permanecer juntos.
  5. Ahora usted tiene un diseño con la lista y la vista gris y la lista no empujará las otras vistas fuera de la pantalla si se pone demasiado grande; Sólo tiene que mover la vista de pie de página a la parte inferior de la pantalla.

    5a. Si está usando RelativeLayout como su diseño raíz, puede hacer lo que sgallego dijo y usar android: layout_alignParentBottom.

    5b. Pero si está utilizando LinearLayout necesita crear un tercer diseño con layout_weigth y ponerlo dentro del diseño del paso 4 y una vista vacía también con layout_weigth para llenar el espacio vacío.

Aquí hay un ejemplo comentado.

 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" > <!-- Header --> <TextView android:id="@+id/RecordStudy_StudyLabel" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/RecordStudy_StudyLabel" android:textSize="@dimen/text_large" /> <!-- Body --> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="vertical" > <!-- This layout encapsules the list and the button that must be immediately below the list with a wrap_content height, so the list plus the button fills only as much space as they need (if the list is not big enouth to fill the entire screen). --> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="vertical" > <!-- Layout with varaible size with a list inside. Using layout_weight tells android that this layout should not grow greater then the screen, but uses only the free space. --> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="vertical" > <!-- Inside this limited height layout, there is a list with height wrap_content so it can grow as much as it needs INSIDE the layout (through scrolling). --> <ListView android:id="@+id/RecordStudy_StudyList" android:layout_width="match_parent" android:layout_height="wrap_content" /> </LinearLayout> <!-- Button immediately below the list --> <Button android:id="@+id/RecordStudy_AddStudy" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/RecordStudy_AddStudy" /> </LinearLayout> <!-- Space between the list and the footer --> <View android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" /> </LinearLayout> <!-- Footer --> <Button android:id="@+id/RecordStudy_ConfirmButton" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="@string/RecordStudy_ConfirmButton" /> </LinearLayout> 

Una solución que funcionó para mí era agregar el acolchado positivo a la parte inferior de la vista de la lista y el relleno negativo a la tapa del "pie de página". Esto funcionará en un diseño lineal o un diseño relativo.

 <ListView android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingBottom="50dp"/> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginTop="-50dp"/> 
  • Restaurar el diseño predeterminado de la barra de acciones
  • Posición aleatoria de TextView
  • Peso relativo del peso
  • ¿Qué es android: layout_marginStart
  • ¿Cuál es el uso del layoutinflator?
  • Vista de desplazamiento horizontal en páginas de desplazamiento horizontal
  • error de layout-large-land-hdpi
  • Android - ScrollView como foursquare con mapas + lista
  • Manejo de barras de acción con dos fragmentos
  • Dividir la pantalla en la tableta android
  • Mostrar fuentes personalizadas o Ver en la sección de vista previa de Android Studio XML
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.