¿Por qué requestLayout se llama directamente después de invalidar
Estoy aprendiendo acerca de las vistas personalizadas y quería aprender acerca de invalidate()
y requestLayout()
.
Consulte esta respuesta y su diagrama:
- ¿Cómo puedo asignar un ID a una vista mediante programación?
- Atributos del mismo nombre en attrs.xml para vista personalizada
- Cómo establecer vistas en RelativeLayout mediante programación?
- Conceptos básicos de Android: ejecutar código en el subproceso de la interfaz de usuario
- Diferentes fling (swipe) de velocidad en diferentes dispositivos Android con la misma densidad
Https://stackoverflow.com/a/25846243/4243687
invalidate()
indica a Android que el estado de la vista ha cambiado y necesita ser redibujado.
requestLayout()
significa que el tamaño de la vista puede haber cambiado y necesita ser re-medido, y luego volver a dibujar.
invalidate()
invocará dispatchDraw()
, draw()
y onDraw()
por lo que vuelve a mostrar la vista.
requestLayout()
por otro lado hace casi todo, desde medir hasta volver a renderizar.
¿Por qué tantos ejemplos (por ejemplo, el código fuente de TextView
) llaman invalidate()
y luego requestLayout()
derecha en la línea siguiente?
- Habilitar longClick en WebView
- Manejo de la rotación de la pantalla en WebView
- Uso de forceLayout (), requestLayout () e invalidate ()
- ¿Cómo puedo inhabilitar todos los eventos táctiles en todos los niños de un ViewGroup?
- Android WebView: Imagen local grande no cargada / mostrada
- MuPDF para Android: opción para el fragmento en su lugar Actividad
- ¿Cuántos WindowInsets hay?
- ¿Qué es android: layout_marginStart
invalidate()
se utiliza específicamente para volver a dibujar el contenido de su vista. El redibujo no ocurre sincrónicamente. En su lugar, indica la región de su vista como no válida para que se vuelva a dibujar durante el ciclo de procesamiento siguiente.
requestLayout()
debe utilizar cuando algo dentro de él posiblemente ha cambiado sus dimensiones. En este caso, la vista principal y todos los demás padres de la jerarquía de vista tendrán que reajustarse a través de un pase de disposición.
Si no está haciendo nada a su vista que cambiaría su tamaño, entonces no tiene que llamar a requestLayout()
.
Si vuelves a mirar los lugares en el código de TextView
donde requestLayout()
está siendo llamado, estará en métodos donde los límites de la vista se verán afectados. Por ejemplo, setPadding()
, setTypeface()
, setCompoundDrawables()
, etc.
Por lo tanto, cuando requestLayout()
se llama, debe ser emparejado con una llamada a invalidar para asegurarse de que toda la vista se vuelve a dibujar.
Extracto pertinente del libro Expert Android que responde a la pregunta:
Debido a que el evento onClick ha provocado que las dimensiones cambien, nuestra vista debe hacerse más grande y tener más espacio. ¿Cómo se expresa esa necesidad de Android, Bueno, solicitamos Layout (). Este método sube la cadena, marcando cada padre de vista que necesita ser re-medido. Cuando el padre final obtiene esta solicitud (la raíz de la vista), el padre programa un recorrido de diseño. Un trazado de disposición puede o no resultar en onDraw, aunque en este caso debería. Como una buena práctica de programación, también llamamos invalidate () para asegurar la fase de dibujo también.
Después de ver el diagrama siguiente , tenía la impresión de que llamar a requestLayout()
eventualmente resultaría en un onDraw
.
Por lo tanto, no habría necesidad de llamarlos juntos porque sería redundante.
invalidate(); requestLayout();
Sin embargo, resulta que ese diagrama es engañoso. Algunas vistas pueden de hecho invalidarse cuando hay un cambio de diseño, pero esto no es una certeza. Llamar requestLayout()
no está garantizado para dar lugar a onDraw
se llama.
Mi fuente (gracias a este comentario ) es el Romain Guy (que es un ingeniero de Android en Google):
RequestLayout () no conduce a un pase de dibujo, pero algunas vistas pueden reaccionar a un cambio de diseño invocando invalidate.
Por lo tanto, para estar seguro de que un relayout dará como resultado un redibujo, entonces debe emparejar un invalidate()
con requestLayout()
. (Lo contrario no es cierto, sin requestLayout()
sólo necesita un redibujo, entonces no hay necesidad de llamar a requestLayout()
. Un único invalidate()
hará.)
Documentos de Android: Creación de una clase de vista
public boolean isShowText() { return mShowText; } public void setShowText(boolean showText) { mShowText = showText; invalidate(); requestLayout(); }
Observe que setShowText invoca invalidate () y requestLayout (). Estas llamadas son cruciales para asegurar que la vista se comporte de forma fiable. Debe invalidar la vista después de cualquier cambio en sus propiedades que pudiera cambiar su apariencia, para que el sistema sepa que debe volver a dibujarse. Asimismo, debe solicitar un nuevo diseño si cambia una propiedad que podría afectar al tamaño o la forma de la vista. Olvidar estas llamadas de método puede causar errores difíciles de encontrar.