He configurado un ViewPager simple que tiene un ImageView con una altura de 200dp en cada página.
Aquí está mi buscapersonas:
pager = new ViewPager(this);
pager.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));
pager.setBackgroundColor(Color.WHITE);
pager.setOnPageChangeListener(listener);
layout.addView(pager);
A pesar de la altura establecida como wrap_content, el localizador siempre llena la pantalla a pesar de que la vista de la imagen es de solo 200dp. Traté de reemplazar la altura del localizador con "200" pero eso me da resultados diferentes con múltiples resoluciones. No puedo agregar "dp" a ese valor. ¿Cómo agrego 200dp al diseño del localizador?
Respuestas:
Anular onMeasure de su
ViewPager
siguiente manera hará que tenga la altura del niño más grande que tiene actualmente.fuente
Otra solución más genérica es llegar
wrap_content
al trabajo.Me he extendido
ViewPager
para anularonMeasure()
. La altura se envuelve alrededor de la primera vista secundaria. Esto podría generar resultados inesperados si las vistas secundarias no tienen exactamente la misma altura. Para eso, la clase se puede ampliar fácilmente para animar, por ejemplo, el tamaño de la vista / página actual. Pero no necesitaba eso.Puede usar este ViewPager en sus diseños XML al igual que el ViewPager original:
Ventaja: este enfoque permite utilizar ViewPager en cualquier diseño, incluido RelativeLayout, para superponer otros elementos de la interfaz de usuario.
Queda un inconveniente: si desea usar márgenes, debe crear dos diseños anidados y darle al interior los márgenes deseados.
Aquí está el código:
fuente
Basé mi respuesta en Daniel López Lacalle y esta publicación http://www.henning.ms/2013/09/09/viewpager-that-simply-dont-measure-up/ . El problema con la respuesta de Daniel es que en algunos casos mis hijos tenían una altura de cero. Desafortunadamente, la solución era medir dos veces.
Esto también le permite establecer una altura en el ViewPager si así lo desea o simplemente envolver_contenido.
fuente
scaleType
y de manera similar,layout_width=match_parent
al igual quelayout_height=wrap_content
? hay como 20dp faltando allí.// super has to be called in the beginning so the child views can be initialized.
<----- Esa fue la razón, tuve que llamarlo al inicio y al final de la función onMeasure. ¡Yippiii, virtual choca los cinco hoy!Estaba respondiendo una pregunta muy similar sobre esto, y encontré esto cuando busqué un enlace para respaldar mis afirmaciones, por suerte :)
Mi otra respuesta:
ViewPager no es compatible,
wrap_content
ya que (generalmente) nunca tiene todos sus hijos cargados al mismo tiempo y, por lo tanto, no puede obtener un tamaño adecuado (la opción sería tener un buscapersonas que cambie de tamaño cada vez que haya cambiado página).Sin embargo, puede establecer una dimensión precisa (por ejemplo, 150dp) y también
match_parent
funciona.También puede modificar las dimensiones dinámicamente desde su código cambiando el
height
atributo-en suLayoutParams
.Para sus necesidades , puede crear ViewPager en su propio archivo xml, con el layout_height establecido en 200dp, y luego en su código, en lugar de crear un nuevo ViewPager desde cero, puede inflar ese archivo xml:
fuente
layout_height
set towrap_content
, pero es aún peor ya que la solución simple para configurarlo en una cantidad fija no funciona.Usando la respuesta de Daniel López Localle , creé esta clase en Kotlin. Espero que te ahorre más tiempo
fuente
Ya me he enfrentado a este problema en varios proyectos y nunca tuve una solución completa. Así que creé un proyecto github WrapContentViewPager como un reemplazo en el lugar para ViewPager.
https://github.com/rnevet/WCViewPager
La solución se inspiró en algunas de las respuestas aquí, pero mejora en:
Actualizado para la versión 24 de la biblioteca de soporte que rompió la implementación anterior.
fuente
Me encontré con el mismo problema. Tenía un ViewPager y quería mostrar un anuncio en el botón. La solución que encontré fue colocar el localizador en un RelativeView y establecer su layout_ave por encima de la ID de la vista que quiero ver debajo. Eso funcionó para mí.
Aquí está mi XML de diseño:
fuente
También me encontré con este problema, pero en mi caso tenía una
FragmentPagerAdapter
que estaba suministrandoViewPager
sus páginas. El problema que tuve fue queonMeasure()
de laViewPager
que se llamó antes de cualquiera de losFragments
hubiese sido creado (y por lo tanto no podía tamaño sí correctamente).Después de un poco de prueba y error, descubrí que el
finishUpdate()
método del FragmentPagerAdapter se llama después deFragments
haber sido inicializado (desdeinstantiateItem()
adentroFragmentPagerAdapter
), y también después / durante el desplazamiento de la página. Hice una pequeña interfaz:que paso a mi
FragmentPagerAdapter
y llamo:que a su vez me permite invocar
setVariableHeight()
miCustomViewPager
implementación:No estoy seguro de que sea el mejor enfoque, me encantarían los comentarios si crees que es bueno / malo / malo, pero parece estar funcionando bastante bien en mi implementación :)
Espero que esto ayude a alguien por ahí!
EDITAR: Olvidé agregar un
requestLayout()
después de llamarsuper.measure()
(de lo contrario, no vuelve a dibujar la vista).También olvidé agregar el relleno de los padres a la altura final.
También dejé de mantener el ancho / alto original MeasureSpecs a favor de crear uno nuevo según sea necesario. Han actualizado el código en consecuencia.
Otro problema que tuve fue que no se dimensionaba correctamente en una
ScrollView
y descubrí que el culpable estaba midiendo al niño enMeasureSpec.EXACTLY
lugar de hacerloMeasureSpec.UNSPECIFIED
. Actualizado para reflejar esto.Todos estos cambios se han agregado al código. Puede consultar el historial para ver las versiones antiguas (incorrectas) si lo desea.
fuente
Otra solución es actualizar la
ViewPager
altura de acuerdo con la altura de la página actual en suPagerAdapter
. Asumiendo que estás creando tusViewPager
páginas de esta manera:Where
mPages
es una lista interna dePageInfo
estructuras que se agrega dinámicamente alPagerAdapter
yCustomImageView
es regularImageView
con elonMeasure()
método de reemplazo que establece su altura de acuerdo con el ancho especificado y mantiene la relación de aspecto de la imagen.Puede forzar la
ViewPager
altura en elsetPrimaryItem()
método:Tenga en cuenta el
Math.max(height, 1)
. Eso corrige un molesto error queViewPager
no actualiza la página mostrada (la muestra en blanco), cuando la página anterior tiene una altura cero (es decir, nula dibujable en elCustomImageView
), cada deslizamiento extraño de ida y vuelta entre dos páginas.fuente
item.mImageView.measure(..)
para obtener las dimensiones correctas en losgetMeasuredXXX()
métodos.Cuando use contenido estático dentro del visor y no desee una animación elegante, puede usar el siguiente visor
fuente
fuente
Desde el código fuente de la aplicación de Android Popcorn time, encontré esta solución que ajusta dinámicamente el tamaño del visor con una agradable animación dependiendo del tamaño del niño actual.
https://git.popcorntime.io/popcorntime/android/blob/5934f8d0c8fed39af213af4512272d12d2efb6a6/mobile/src/main/java/pct/droid/widget/WrappingViewPager.java
fuente
En caso de que necesite ViewPager que ajuste su tamaño a cada niño , no solo al más grande, he escrito un código que lo hace. Tenga en cuenta que no hay animación sobre ese cambio (no es necesario en mi caso)
android: minHeight flag también es compatible.
fuente
Respuesta mejorada de Daniel López Lacalle , reescrita en Kotlin :
fuente
Me encontré con el mismo problema, y también tuve que hacer que ViewPager se ajustara a su contenido cuando el usuario se desplazaba entre las páginas. Usando la respuesta anterior de cybergen, definí el método onMeasure de la siguiente manera:
De esta manera, el método onMeasure establece la altura de la página actual que muestra ViewPager.
fuente
Nada de lo sugerido anteriormente funcionó para mí. Mi caso de uso es tener 4 ViewPagers personalizados
ScrollView
. La parte superior se mide en función de la relación de aspecto y el resto simplementelayout_height=wrap_content
. He probado las soluciones de cybergen , Daniel López Lacalle . Ninguno de ellos funciona completamente para mí.Supongo que el cybergen no funciona en la página> 1 es porque calcula la altura del buscapersonas en función de la página 1, que se oculta si se desplaza más.
Tanto las sugerencias de cybergen como las de Daniel López Lacalle tienen un comportamiento extraño en mi caso: 2 de 3 se cargan bien y 1 altura aleatoria es 0. Aparece que
onMeasure
se llamó antes de que se poblaran los niños. Así que se me ocurrió una mezcla de estas 2 respuestas + mis propias soluciones:La idea es permitir
ViewPager
calcular las dimensiones de los niños y guardar la altura calculada de la primera página en los parámetros de diseño delViewPager
. No olvide establecer la altura de diseño del fragmento parawrap_content
que, de lo contrario, pueda obtener height = 0. He usado este:Tenga en cuenta que esta solución funciona muy bien si todas sus páginas tienen la misma altura . De lo contrario, debe volver a calcular la
ViewPager
altura según el elemento secundario activo actual. No lo necesito, pero si sugiere la solución, me complacería actualizar la respuesta.fuente
Para las personas que tienen este problema y codifican para Xamarin Android en C #, esta también podría ser una solución rápida:
Esto es principalmente útil si las vistas de sus hijos son de la misma altura. De lo contrario, se le pedirá que almacene algún tipo de valor de "altura mínima" sobre todos los elementos secundarios con los que verifique, e incluso entonces es posible que no desee tener espacios vacíos visibles debajo de las vistas secundarias más pequeñas.
Sin embargo, la solución en sí no es suficiente para mí, pero eso se debe a que mis elementos secundarios son listViews y su MeasuredHeight no se calcula correctamente, al parecer.
fuente
Tengo una versión de WrapContentHeightViewPager que funcionaba correctamente antes de API 23 que redimensionará la base de altura de la vista principal en la vista secundaria actual seleccionada.
Después de actualizar a API 23, dejó de funcionar. Resulta que la solución anterior estaba usando
getChildAt(getCurrentItem())
para obtener la vista secundaria actual para medir lo que no funciona. Ver solución aquí: https://stackoverflow.com/a/16512217/1265583A continuación funciona con API 23:
fuente
requestLayout()
para que la altura se ajuste a medida que avanzamos de una pestaña a la siguiente. ¿Recuerdas por quésuper
hay que llamar dos veces? Me di cuenta de que no funcionará de otra manera.El siguiente código es lo único que me funcionó
1. Use esta clase para declarar un HeightWrappingViewPager:
2. Inserte el localizador de vista de ajuste de altura en su archivo xml:
3. Declare su localizador de vistas:
fuente
Edito la respuesta de cybergen para hacer que el visor cambie de altura dependiendo del elemento seleccionado. La clase es la misma que la de cybergen, pero agregué un Vector de enteros que es todas las alturas de vistas secundarias del visor y podemos acceder a él cuando cambie la página para actualizar la altura.
Esta es la clase:
Luego, en su actividad, agregue un OnPageChangeListener
Y aquí está xml:
Por favor corrija mi inglés si es necesario
fuente
heights
lista puede aumentar infinito.measure
, se llamaría varias veces. Puede aumentar la lista de alturas. Otra situación es que el usuario puede llamarrequestLayout
(osetLayoutParams
método, al igual que lo hizo) para este viewPager manualmente, también medirá varias veces.Si el
ViewPager
que está usando es hijo de unScrollView
AND y tiene unPagerTitleStrip
hijo, deberá usar una ligera modificación de las excelentes respuestas que ya se proporcionaron. Como referencia, mi XML se ve así:En su
onMeasure
tiene que AGREGAR la altura medida delPagerTitleStrip
si se encuentra uno. De lo contrario, su altura no se considerará la altura más grande de todos los niños a pesar de que ocupa espacio adicional.Espero que esto ayude a alguien más. Lamento que sea un truco ...
fuente
La mayoría de las soluciones que veo aquí parecen estar haciendo una doble medición: primero medir las vistas secundarias y luego llamar al
super.onMeasure()
Se me ocurrió una costumbre
WrapContentViewPager
que es más eficiente, funciona bien con RecyclerView y FragmentPuedes consultar la demo aquí:
github / ssynhtn / WrapContentViewPager
y el código de la clase aquí: WrapContentViewPager.java
fuente
Tengo un escenario similar (pero más complejo). Tengo un cuadro de diálogo que contiene un ViewPager.
Una de las páginas secundarias es corta, con una altura estática.
Otra página secundaria siempre debe ser lo más alta posible.
Otra página secundaria contiene un ScrollView, y la página (y, por lo tanto, el cuadro de diálogo completo) debe WRAP_CONTENT si el contenido del ScrollView no necesita la altura total disponible para el cuadro de diálogo.
Ninguna de las respuestas existentes funcionó completamente para este escenario específico. Espera, es un viaje lleno de baches.
Muchas gracias a @Raanan por el código para medir vistas y medir la altura de la decoración. Me encontré con problemas con su biblioteca, la animación tartamudeó, y creo que mi ScrollView no se desplazaría cuando la altura del diálogo fuera lo suficientemente corta como para requerirlo.
fuente
en mi caso agregar
clipToPadding
solucionó el problema.¡Salud!
fuente
Mi caso agregando Android: fillViewport = "true" resolvió el problema
fuente
En mi caso, necesitaba un visor con un wrap_content para el elemento y la animación actualmente seleccionados al aplicar el tamaño. A continuación puedes ver mi implementación. ¿Alguien puede ser útil?
Agregue attrs.xml en el proyecto:
Y use:
fuente
Este ViewPager solo cambia el tamaño a los hijos visibles actuales (no el mayor de sus hijos reales)
La idea de https://stackoverflow.com/a/56325869/4718406
}
fuente
Mida la altura de ViewPager:
conjunto de llamadasPrimaryView (Ver) :
fuente
Dar diseño principal de ViewPager como
NestedScrollView
No te olvides de configurar
android:fillViewport="true"
Esto estirará la vista de desplazamiento y el contenido de su hijo para llenar la ventana gráfica.
https://developer.android.com/reference/android/widget/ScrollView.html#attr_android:fillViewport
fuente
Puede cambiar a ViewPager2. Es una versión actualizada de ViewPager. Hace lo mismo que ViewPager pero de una manera más inteligente y eficiente. ViewPager2 viene con una variedad de nuevas características. Por supuesto, ViewPager2 ha resuelto el problema de envoltura de contenido.
De los documentos de Android: "ViewPager2 reemplaza a ViewPager, abordando la mayoría de los puntos débiles de su predecesor, incluido el soporte de diseño de derecha a izquierda, orientación vertical, colecciones de fragmentos modificables, etc."
Recomiendo este artículo para principiantes:
https://medium.com/google-developer-experts/exploring-the-view-pager-2-86dbce06ff71
fuente