Estoy un poco confundido acerca de las funciones de forceLayout()
, requestLayout()
y invalidate()
métodos de la View
clase.
¿Cuándo serán llamados?
android
android-layout
android-view
sdabet
fuente
fuente
TextView
. Pensé que tal vez querrían dibujarView
por última vez antes de cambiar sus parámetros relacionados con el diseño, pero realmente no tiene ningún sentido si pensamos en que esas llamadas se invocan en un orden diferente (y llamaninvalidate()
inmediatamente despuésrequestLayout()
enTextView
también). Tal vez merece otra pregunta sobre StackOverflow :)?invalidate()
yrequestLayout()
) correctamente. El propósito de esos métodos es decirView
qué tipo de invalidación (como lo llamó) ha sucedido. No es comoView
decidir qué camino seguir después de llamar a uno de esos métodos. La lógica detrás de elegir laView
ruta del ciclo de vida es elegir el método adecuado para llamarse a sí mismo. Si hay algo relacionado con el cambio de tamaño,requestLayout()
debe llamarse, si solo hay un cambio visual sin un cambio de tamaño, debe llamarinvalidate()
.View
de alguna manera, por ejemplo, obtiene corrienteLayoutParams
de aView
y los modifica, pero NO llama a ningunorequestLayout
osetLayoutParams
(que llamarequestLayout
internamente), puede llamarinvalidate()
tanto como desee, y elView
no va a pasar por el proceso de medida de la disposición, por lo tanto, no va a cambiar su tamaño. Si no le dice alView
que su tamaño ha cambiado (con unarequestLayout
llamada al método), entonces elView
va a asumir que no lo hizo, y elonMeasure
yonLayout
no será llamado.invalidate()
Las llamadas
invalidate()
se realizan cuando desea programar un nuevo dibujo de la vista. Con el tiempo, se loonDraw
llamará (pronto, pero no inmediatamente). Un ejemplo de cuándo una vista personalizada lo llamaría es cuando una propiedad de texto o color de fondo ha cambiado.La vista se volverá a dibujar pero el tamaño no cambiará.
requestLayout()
Si algo sobre su vista cambia que afectará el tamaño, entonces debe llamar
requestLayout()
. Esto se activaráonMeasure
yonLayout
no solo para esta vista, sino también en toda la línea para las vistas principales.No
requestLayout()
se garantiza queonDraw
llamar resulte en un (contrario a lo que implica el diagrama en la respuesta aceptada), por lo que generalmente se combina coninvalidate()
.Un ejemplo de esto es cuando una etiqueta personalizada tiene su propiedad de texto cambiada. La etiqueta cambiaría de tamaño y, por lo tanto, debe volverse a medir y volver a dibujar.
forceLayout()
Cuando
requestLayout()
se llama a un grupo de vista principal, no es necesario volver a medir y retransmitir sus vistas secundarias. Sin embargo, si un niño debe ser incluido en la nueva medición y retransmisión, entonces puede llamarforceLayout()
al niño.forceLayout()
solo funciona en un niño si ocurre junto con unrequestLayout()
en su padre directo. LlamarforceLayout()
por sí solo no tendrá ningún efecto ya que no activa unrequestLayout()
árbol de la vista.Lea estas preguntas y respuestas para obtener una descripción más detallada de
forceLayout()
.Estudio adicional
View
código fuentefuente
requestLayout()
antesinvalidate()
si lo desea. Ninguno de los dos hace un diseño o dibuja de inmediato. Más bien, establecen banderas que eventualmente resultarán en un relevo y un nuevo dibujo.Aquí puede encontrar alguna respuesta: http://developer.android.com/guide/topics/ui/how-android-draws.html
Para mí, una llamada para
invalidate()
actualizar solo la vista y una llamada pararequestLayout()
actualizar la vista y calcular el tamaño de la vista en la pantalla.fuente
utiliza invalidate () en una vista que desea volver a dibujar, hará que se invoque onDraw (Canvas c) y requestLayout () hará que todo el renderizado del diseño (fase de medición y fase de posicionamiento) vuelva a ejecutarse. Debe usarlo si está cambiando el tamaño de la vista secundaria en tiempo de ejecución, pero solo en casos particulares como restricciones de la vista principal (con esto quiero decir que la altura o el ancho principal son WRAP_CONTENT y, por lo tanto, mida los elementos secundarios antes de que puedan envolverlos nuevamente)
fuente
Esta respuesta no es correcta sobre
forceLayout()
.Como puedes ver en el código de
forceLayout()
, simplemente marca la vista como "necesita una retransmisión", pero no programa ni desencadena esa retransmisión. El relevo no sucederá hasta que en algún momento en el futuro el padre de la vista se haya presentado por alguna otra razón.También hay un problema mucho mayor al usar
forceLayout()
yrequestLayout()
:Digamos que has llamado
forceLayout()
a una vista. Ahora, al llamarrequestLayout()
a un descendiente de esa vista, Android recurrirá recursivamenterequestLayout()
a los antepasados de ese descendiente. El problema es que detendrá la recursividad en la vista a la que ha llamadoforceLayout()
. Por lo tanto, larequestLayout()
llamada nunca llegará a la raíz de la vista y, por lo tanto, nunca programará un pase de diseño. Un subárbol completo de la jerarquía de vistas está esperando un diseño y llamarrequestLayout()
a cualquier vista de ese subárbol no causará un diseño. Solo invocarrequestLayout()
cualquier vista fuera de ese subárbol romperá el hechizo.Consideraría la implementación de
forceLayout()
(y cómo afectarequestLayout()
que se rompa y nunca debe usar esa función en su código.fuente
View
y descubriendo el problema yo mismo y depurándolo.forceLayout()
API: en realidad no fuerza un pase de diseño, sino que simplemente cambia un indicador que se está observandoonMeasure()
, peroonMeasure()
no se llamará a menos que se llamerequestLayout()
un explícitoView#measure()
. Eso significa queforceLayout()
debe ser emparejado conrequestLayout()
. Por otro lado, ¿por qué entonces actuarforceLayout()
si todavía necesito hacerlorequestLayout()
?requestLayout()
hace todo lo queforceLayout()
también hace.forceLayout
tiene sentido. Entonces, al final, está muy mal nombrado y documentado.invalidate()
--->onDraw()
del hilo de la interfaz de usuariopostInvalidate()
--->onDraw()
del hilo de fondorequestLayout()
--->onMeasure()
yonLayout()
Y no necesariamenteonDraw()
forceLayout()
--->onMeasure()
yonLayout()
SOLO SI el padre directo llamórequestLayout()
.fuente