studio programacion para móviles español edición desarrollo desarrollar curso aprende aplicaciones android resize rendering custom-view viewgroup

para - manual programacion android español pdf



Las vistas dentro de un grupo de vistas personalizado no se procesan después de un cambio de tamaño (2)

Me estoy topando con un problema que me ha dejado perplejo y esperaba que alguien pudiera darme algunos consejos.

Estoy trabajando en una aplicación que utiliza un grupo de vistas personalizado (en realidad, un FrameLayout que contiene un RelativeLayout) para representar un calendario de eventos. Los eventos dentro del calendario se representan como vistas que se dimensionan de acuerdo con la duración del evento y el tamaño de la vista que contiene.

Estoy encontrando un problema que se produce cuando se cambia el tamaño del FrameLayout que contiene. La implementación actual elimina todas las vistas que representan los eventos e intenta agregar nuevos y calcular sus tamaños según el tamaño actual del FrameLayout. Este trabajo se está activando a través del método de visualización onSizeChanged () que se invalida en FrameLayout.

Cuando se cambia el tamaño de la vista, este código se ejecuta y las vistas se actualizan, sin embargo, ninguno de ellos realmente se muestra en la pantalla ... las vistas contenidas en FrameLayout simplemente no son visibles. Si carga la vista en la herramienta de visualización de jerarquías, forman parte del árbol de vistas y se describen en la descripción general en las posiciones en las que deben estar, pero no se muestran. (Tenga en cuenta que las vistas son visibles en el renderizado inicial del FrameLayout ... solo después de un cambio de tamaño desaparecen).

Parece que el orden de los eventos durante el cambio de tamaño es el siguiente:

onMeasure() onMeasure() onSizeChanged() onLayout()

Llamar a requestLayout () después de restablecer las vistas (dentro de onSizeChanged ()) parece no tener efecto. Sin embargo, si causo algún retraso antes de llamar a requestLayout (), las vistas se vuelven visibles. Puedo causar este retraso generando un hilo y durmiendo, o creando un botón ficticio que simplemente llame a requestLayout () y presionándolo después del cambio de tamaño, o incluso este truco feo colocado al final de onSizeChanged ():

post(new Runnable() { public void run() { requestLayout(); } });

Cuando uso este truco, las vistas contenidas están visibles y el orden de los eventos es el siguiente:

onMeasure() onMeasure() onSizeChanged() onLayout() onMeasure() onMeasure() onLayout()

Así que parece que forzar una segunda pasada de medida (después de que se haya modificado el árbol de vistas) hace que las vistas contenidas sean visibles como deberían ser. Por qué retrasar la llamada a requestLayout () hace esto es un misterio para mí.

¿Alguien puede proporcionar alguna información sobre lo que estoy haciendo mal?

Me doy cuenta de que esto es algo difícil de seguir sin mirar un código, así que he creado una pequeña aplicación de muestra que muestra mi problema y la puso a disposición en Github:

https://github.com/MichaelSims/ViewGroupResizeTest

El truco que mencioné anteriormente está comprometido con una rama separada:

https://github.com/MichaelSims/ViewGroupResizeTest/tree/post-runnable-hack

Si puedo proporcionar información adicional, hágamelo saber y gracias de antemano.


Me encuentro con el mismo problema.

Mi onMeasure () fue algo como esto:

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); ... //calculate new width and height here ... setMeasuredDimension(newMeasureSpecWidth, newMeasureSpecHeight); }

Mi error fue que estaba llamando a super.onMeasure () en la primera línea de onMeasure (), por lo que los hijos internos de mi ViewGroup se calculaban en función de un tamaño que estaba a punto de cambiar.

Así que mi solución estaba haciendo algo como esto:

@Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { ... //calculate new width and height here ... int newMeasureSpecWidth = MeasureSpec.makeMeasureSpec(newWidth, MeasureSpec.EXACTLY); int newMeasureSpecHeight = MeasureSpec.makeMeasureSpec(newHeight, MeasureSpec.EXACTLY); super.onMeasure(newMeasureSpecWidth, newMeasureSpecHeight); }

Así que estaba configurando el nuevo tamaño para mi ViewGroup usando la llamada a super.onMeasure (), y luego está comunicando el nuevo tamaño a sus hijos.

Recuerde: el contrato cuando anula onMeasure () es que debe llamar a setMeasuredDimension () (y puede lograrlo llamando al método en sí mismo o llamando a super.onMeasure ())


No es un hack, es cómo se supone que funciona. onSizeChanged () se invoca como parte del pase de diseño, y no puede / no debe solicitarLayout () durante un pase de diseño. Es correcto publicar un requestLayout () en la cola de eventos para indicar que ha cambiado la jerarquía de vistas durante un pase de diseño.