He buscado soluciones para este problema, y la única respuesta que puedo encontrar parece ser " no coloque un ListView en un ScrollView ". Sin embargo, aún no he visto ninguna explicación real de por qué . La única razón por la que puedo encontrar es que Google no cree que debas hacer eso. Bueno, yo sí, así que lo hice.
Entonces la pregunta es, ¿cómo puede colocar un ListView en un ScrollView sin colapsar a su altura mínima?
ListView
.ListView
puede tener múltiples estilos de fila, además de filas no seleccionables.Respuestas:
Usar a
ListView
para que no se desplace es extremadamente costoso y va en contra de todoListView
. NO deberías hacer esto. Solo usa unLinearLayout
en su lugar.fuente
How can I put a ListView into a ScrollView without it collapsing?
... Puedes decir que no debes hacerlo, pero también dar una respuesta sobre cómo hacerlo, es una buena respuesta. Usted sabe que un ListView tiene algunas otras características interesantes además del desplazamiento, características que LinearLayout no tiene.Aquí está mi solución. Soy bastante nuevo en la plataforma Android, y estoy seguro de que esto es un poco complicado, especialmente en la parte de llamar a .measure directamente y configurar la
LayoutParams.height
propiedad directamente, pero funciona.Todo lo que tiene que hacer es llamar
Utility.setListViewHeightBasedOnChildren(yourListView)
y se redimensionará para acomodar exactamente la altura de sus elementos.fuente
LinearLayout
que a no tiene todas las sutilezas inherentes de aListView
: no tiene divisores, vistas de encabezado / pie de página, un selector de lista que coincida con los colores del tema de la interfaz de usuario del teléfono, etc. Honestamente, no hay razón por la que no pueda desplazarse el contenedor interno hasta que llegue al final y luego deje de interceptar eventos táctiles para que el contenedor externo se desplace. Todos los navegadores de escritorio hacen esto cuando usas la rueda de desplazamiento. El propio Android puede manejar el desplazamiento anidado si está navegando a través del trackball, entonces ¿por qué no a través del tacto?listItem.measure(0,0)
arrojará un NPE si listItem es una instancia de ViewGroup.listItem.measure
if (listItem instanceof ViewGroup) listItem.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
int totalHeight = listView.getPaddingTop() + listView.getPaddingBottom();
ListView
puede contener elementos de altura variable. La llamada agetMeasuredHeight()
solo devuelve la altura mínima objetivo en lugar de la altura real. Intenté usar en sugetHeight()
lugar, pero esto devuelve 0. ¿Alguien tiene alguna idea sobre cómo abordar esto?Esto definitivamente funcionará ............
Debe reemplazar su
<ScrollView ></ScrollView>
archivo XML de diseño con esteCustom ScrollView
como<com.tmd.utils.VerticalScrollview > </com.tmd.utils.VerticalScrollview >
fuente
En lugar de poner
ListView
dentro de aScrollView
, podemos usarListView
como aScrollView
. Las cosas que tienen que estar adentroListView
se pueden poner dentro delListView
. SeListView
pueden colocar otros diseños en la parte superior e inferior agregando diseños al encabezado y pie de páginaListView
. Así que todoListView
te dará una experiencia de desplazamiento.fuente
Hay muchas situaciones en las que tiene mucho sentido tener ListView en un ScrollView.
Aquí está el código basado en la sugerencia de DougW ... funciona en un fragmento, requiere menos memoria.
llame a setListViewHeightBasedOnChildren (vista de lista) en cada vista de lista incrustada.
fuente
ListView ya es capaz de medirse para ser lo suficientemente alto como para mostrar todos los elementos, pero no hace esto cuando simplemente especifica wrap_content (MeasureSpec.UNSPECIFIED). Lo hará cuando tenga una altura con MeasureSpec.AT_MOST. Con este conocimiento, puede crear una subclase muy simple para resolver este problema que funciona mucho mejor que cualquiera de las soluciones publicadas anteriormente. Aún debe usar wrap_content con esta subclase.
La manipulación de heightMeasureSpec para que sea AT_MOST con un tamaño muy grande (Integer.MAX_VALUE >> 4) hace que ListView mida a todos sus hijos hasta la altura dada (muy grande) y establezca su altura en consecuencia.
Esto funciona mejor que las otras soluciones por algunas razones:
En el lado negativo, podría argumentar que hacer esto depende de un comportamiento indocumentado en el SDK que podría cambiar. Por otro lado, podría argumentar que así es como realmente debería funcionar wrap_content con ListView y que el comportamiento actual de wrap_content simplemente está roto.
Si le preocupa que el comportamiento pueda cambiar en el futuro, simplemente copie la función onMeasure y las funciones relacionadas de ListView.java y en su propia subclase, luego haga que la ruta AT_MOST a través de onMeasure se ejecute también para UNSPECIFIED.
Por cierto, creo que este es un enfoque perfectamente válido cuando trabajas con un pequeño número de elementos de la lista. Puede ser ineficiente en comparación con LinearLayout, pero cuando el número de elementos es pequeño, usar LinearLayout es una optimización innecesaria y, por lo tanto, una complejidad innecesaria.
fuente
Hay una configuración incorporada para ello. En el ScrollView:
En Java
Romain Guy lo explica en profundidad aquí: http://www.curious-creature.org/2010/08/15/scrollviews-handy-trick/
fuente
Usted crea ListView personalizado que no es desplazable
En su archivo de recursos de diseño
En archivo Java
Cree un objeto de su CustomListview en lugar de ListView como: NonScrollListView non_scroll_list = (NonScrollListView) findViewById (R.id.lv_nonscroll_list);
fuente
No podríamos usar dos desplazamientos simultáneos. Obtendremos la longitud total de ListView y expandiremos la vista de lista con la altura total. Luego, podemos agregar ListView en ScrollView directamente o usando LinearLayout porque ScrollView tiene directamente un hijo. copie el método setListViewHeightBasedOnChildren (lv) en su código y expanda la vista de lista, luego puede usar la vista de lista dentro de la vista de desplazamiento. \ layout xml file
Método onCreate en la clase de actividad:
fuente
Esta es una combinación de las respuestas de DougW, Good Guy Greg y Paul. Descubrí que todo era necesario al intentar usar esto con un adaptador de vista de lista personalizado y elementos de lista no estándar; de lo contrario, la vista de lista bloqueó la aplicación (también se bloqueó con la respuesta de Nex):
fuente
No debe poner un ListView en un ScrollView porque un ListView ya es un ScrollView. Eso sería como poner un ScrollView en un ScrollView.
¿Qué está tratando de lograr?
fuente
Convertí @ DougW's
Utility
en C # (usado en Xamarin). Lo siguiente funciona bien para los elementos de altura fija en la lista, y será mayormente bueno, o al menos un buen comienzo, si solo algunos de los elementos son un poco más grandes que el elemento estándar.Gracias @DougW, esto me sacó de apuros cuando tuve que trabajar con OtherPeople'sCode. :-)
fuente
setListViewHeightBasedOnChildren()
método? Porque no funciona todo el tiempo para mí.Esto es lo único que funcionó para mí:
en Lollipop en adelante puedes usar
Esto habilita o deshabilita el desplazamiento anidado para esta vista si necesita compatibilidad con versiones anteriores del sistema operativo, tendrá que usar RecyclerView.
fuente
Antes no era posible. Pero con el lanzamiento de las nuevas bibliotecas de Appcompat y las bibliotecas de diseño, esto se puede lograr.
Solo tienes que usar NestedScrollView https://developer.android.com/reference/android/support/v4/widget/NestedScrollView.html
No sé si funcionará con Listview o no, pero funciona con RecyclerView.
Fragmento de código:
fuente
hey tuve un problema similar. Quería mostrar una vista de lista que no se desplazara y descubrí que manipular los parámetros funcionaba, pero era ineficiente y se comportaría de manera diferente en diferentes dispositivos ... como resultado, esta es una parte de mi código de programación que realmente lo hace de manera muy eficiente .
Nota: si usa esto,
notifyDataSetChanged();
no funcionará según lo previsto, ya que las vistas no se volverán a dibujar. Haga esto si necesita una soluciónfuente
Hay dos problemas al usar un ListView dentro de un ScrollView.
1- ListView debe expandirse completamente a la altura de sus hijos. este ListView resuelve esto:
La altura del divisor debe ser 0, use relleno en las filas en su lugar.
2- El ListView consume eventos táctiles, por lo que ScrollView no se puede desplazar como de costumbre. Este ScrollView resuelve este problema:
¡Esta es la mejor manera que encontré para hacer el truco!
fuente
Una solución que uso es agregar todo el contenido de ScrollView (lo que debería estar arriba y debajo de listView) como headerView y footerView en ListView.
Así funciona, también se convierte el convertview como debería ser.
fuente
gracias al código de Vinay, aquí está mi código para cuando no puedes tener una vista de lista dentro de una vista de desplazamiento, pero necesitas algo así
el relativo diseño permanece dentro de una vista de desplazamiento para que todo se pueda desplazar :)
fuente
Aquí hay una pequeña modificación en la respuesta de @djunod que necesito para que funcione perfectamente:
fuente
intente esto, esto funciona para mí, olvidé dónde lo encontré, en algún lugar del desbordamiento de la pila, no estoy aquí para explicarle por qué no funciona, pero esta es la respuesta :).
EDITAR!, Finalmente descubrí de dónde saqué el código. aquí ! : ListView dentro de ScrollView no se desplaza en Android
fuente
Aunque los métodos sugeridos setListViewHeightBasedOnChildren () funcionan en la mayoría de los casos, en algunos casos, especialmente con muchos elementos, noté que los últimos elementos no se muestran. Así que decidí imitar una versión simple del comportamiento de ListView para reutilizar cualquier código de Adaptador, aquí está la alternativa de ListView:
fuente
Todas estas respuestas están mal !!! Si está intentando colocar una vista de lista en una vista de desplazamiento, debe repensar su diseño. Está intentando colocar un ScrollView en un ScrollView. Interferir con la lista perjudicará el rendimiento de la lista. Fue diseñado para ser así por Android.
Si realmente desea que la lista esté en el mismo desplazamiento que los otros elementos, todo lo que tiene que hacer es agregar los otros elementos a la parte superior de la lista utilizando una simple instrucción de cambio en su adaptador:
El adaptador de lista puede manejar todo, ya que solo muestra lo que está visible.
fuente
Todo este problema desaparecería si LinearLayout tuviera un método setAdapter, porque cuando le dijeras a alguien que lo usara, la alternativa sería trivial.
Si realmente desea un ListView de desplazamiento dentro de otra vista de desplazamiento, esto no ayudará, pero de lo contrario al menos le dará una idea.
Debe crear un adaptador personalizado para combinar todo el contenido sobre el que desea desplazarse y configurar el adaptador de ListView para eso.
No tengo un código de muestra a mano, pero si quieres algo así.
Luego debe crear un adaptador que represente todo ese contenido. Los ListView / Adapters son lo suficientemente inteligentes como para manejar diferentes tipos también, pero debe escribir el adaptador usted mismo.
La API de la interfaz de usuario de Android simplemente no es tan madura como casi todo lo demás, por lo que no tiene las mismas características que otras plataformas. Además, al hacer algo en Android, debe estar en una mentalidad de Android (Unix) donde espera que para hacer cualquier cosa, probablemente tenga que ensamblar la funcionalidad de partes más pequeñas y escribir un montón de su propio código para obtenerlo trabajo.
fuente
Cuando lo colocamos
ListView
dentroScrollView
surgen dos problemas. UnoScrollView
mide a sus hijos en modo NO ESPECIFICADO, por lo queListView
establece su propia altura para acomodar solo un elemento (no sé por qué), otroScrollView
intercepta el evento táctil paraListView
que no se desplace.Pero nosotros podemos colocar
ListView
en el interiorScrollView
con un poco de solución. Esta publicación , por mí, explica la solución. Con esta solución también podemos conservarListView
la función de reciclaje.fuente
En lugar de colocar la vista de lista dentro de la Vista de desplazamiento, coloque el resto del contenido entre la vista de lista y la apertura de la Vista de desplazamiento como una vista separada y establezca esa vista como el encabezado de la vista de lista. Por lo tanto, finalmente terminará solo con la vista de lista a cargo de Scroll.
fuente
Esta biblioteca es la solución más fácil y rápida al problema.
fuente
Aquí está mi versión del código que calcula la altura total de la vista de lista. Esta funciona para mí:
fuente