El principio de funcionamiento de Ver dibujo en el dibujo de la interfaz de usuario de Android
Este es el segundo artículo sobre el análisis del proceso de dibujo de AndroidUI. Analiza principalmente el proceso específico de cómo se dibuja la Vista en la interfaz.
ViewRoot corresponde a la clase ViewRootImpl, que es el vínculo entre WindowManager y DecorView. Los tres procesos principales de View se completan a través de ViewRoot. En ActivityThread, cuando se crea el objeto Actividad, DecorView se agregará a la Ventana, se creará el objeto ViewRootImpl y el objeto ViewRootImpl se asociará con DecorView.
El proceso de medición determina el ancho/alto de la Vista. Una vez completada la Medición, puede obtener el ancho/alto medido de la Vista a través de los métodos getMeasuredWidth y getMeasuredHeight. En casi todos los casos, es equivalente. al ancho/alto final de la Vista, excepto en circunstancias especiales. El proceso de Diseño determina las coordenadas y el ancho/alto real de los cuatro vértices de la Vista. Una vez finalizado, puede obtener las posiciones de los cuatro vértices de la Vista a través de getTop, getBottom, getLeft y getRight, y puede obtener la Vista a través de getWidth y getHeight. métodos. El ancho/alto final. El proceso de dibujo determina la visualización de la Vista. Solo después de que se completa el método de dibujo se puede presentar el contenido de la Vista en la pantalla.
Como vista de nivel superior, DecorView generalmente contiene un LinearLayout vertical. Hay dos partes en este LinearLayout, la barra de título de arriba y la barra de contenido de abajo. En Actividad, el archivo de diseño que configuramos a través de setContentView en realidad se agrega a la columna de contenido, y la identificación de la columna de contenido es contenido. El contenido se puede obtener mediante el siguiente método: ViewGroup content = findViewById(R.android.id.content). La vista configurada se puede obtener a través de content.getChildAt(0). DecorView es en realidad un FrameLayout. Los eventos en la capa Ver primero pasan a través de DecorView y luego pasan a nuestra Vista.
MeasureSpec representa un valor int de 32 bits, los 2 bits superiores representan SpecMode y los 30 bits inferiores representan SpecMode se refiere al modo de medición y SpecSize se refiere al tamaño de especificación en un determinado modo de medición. .
Hay tres tipos de SpecMode, de la siguiente manera:
NO ESPECIFICADO
EXACTAMENTE
AT_MOST
LayoutParams necesita para ser el mismo que el padre Solo el contenedor puede determinar la MeasureSpec de la Vista, que determina además el ancho/alto de la Vista.
El proceso de conversión de MeasureSpec es ligeramente diferente para la Vista de nivel superior, es decir, DecorView y la Vista normal.
Para DecorView, su MeasureSpec está determinada por el tamaño de la ventana y sus propios LayoutParams
Para la vista normal, su MeasureSpec está determinada por la MeasureSpec del contenedor principal y sus propios Layoutparams
<; p> p>Una vez que se determina MeasureSpec, onMeasure puede determinar el ancho/alto medido de la Vista.
Resumen
Cuando el ancho y el alto de la Vista secundaria adoptan wrap_content, independientemente de si el modo del contenedor principal es el modo preciso o el modo máximo, el modo de la Vista secundaria es siempre el resto del contenedor principal en modo máximo.
El flujo de trabajo de Ver se refiere principalmente a los tres procesos principales de medir, diseñar y dibujar, a saber, medición, diseño y dibujo. Entre ellos, medir determina el ancho/alto medido de la Vista, el diseño determina el ancho/alto final de la vista y la posición de los cuatro vértices, y dibujar dibuja la Vista en la pantalla.
El proceso de medición depende de la situación. Si es solo una vista original, el proceso de medición se completará mediante el método de medición. Si es un ViewGroup, además de completar su propio proceso de medición. También atravesará y llamará a todas las subvistas. El método de medida del elemento, cada subelemento ejecuta este proceso de forma recursiva.
Si es una Vista original, entonces el proceso de medición se completa a través del método de medida. En el método de medida, se llamará al método onMeasure de la Vista. La implementación predeterminada del método onMeasure se define en. la clase View:
Primero eche un vistazo al código fuente de los métodos getSuggestedMinimumWidth y getSuggestedMinimumHeight:
Como puede ver, el método getMinimumWidth obtiene el ancho original del Drawable. Si el ancho original existe (es decir, intrinsicWidth gt; 0 se cumple), entonces el ancho original se devuelve directamente; si no hay un ancho original (es decir, intrinsicWidth gt; 0 no se cumple), se devuelve 0.
A continuación, observe el método getDefaultSize más importante:
Si specMode es MeasureSpec.UNSPECIFIED, es decir, no se especifica ningún modo, entonces el tamaño pasado por el parámetro del método se devuelve como el ancho y alto medidos de la Vista;
Si specMode no es MeasureSpec.UNSPECIFIED, es decir, modo máximo o modo preciso, entonces el specSize extraído de MeasureSpec se devuelve como el ancho y alto medidos de la Vista; Vista.
Eche un vistazo a la tabla hace un momento:
Cuando specMode es EXACTLY o AT_MOST, y el parámetro de diseño de View es wrap_content o match_parent, el specSize dado a View es parentSize. Será mayor que el ancho y alto mínimos recomendados. Esto no es lo que esperábamos. Porque configuramos wrap_content para Ver porque esperamos que el tamaño de Vista pueda ser suficiente para envolver su contenido.
Por lo tanto:
Si es un ViewGroup, además de completar su propio proceso de medición, también recorrerá para llamar a los métodos de medición de todos los subelementos y cada subelemento. El elemento ejecutará recursivamente el proceso de medida.
ViewGroup no anula el método onMeasure de View, pero proporciona los métodos MeasureChildren, MeasureChild y MeasureChildWithMargins específicamente para medir elementos secundarios.
Si es una Vista, su posición se determina en su método de diseño (específicamente, la posición de los cuatro vértices de la Vista se establece mediante el método setFrame, es decir, inicializando mLeft, mRight, mTop, mPor debajo de estos cuatro valores), el proceso de diseño ha terminado.
Si es un ViewGroup, entonces su método de diseño solo determina la posición del ViewGroup en sí. Para determinar la posición del subelemento, debe anular el método onLayout en el método onLayout; Se llamará al subelemento. El método de diseño del subelemento determina su posición en su método de diseño, de modo que se pasa capa por capa para completar el proceso de diseño de todo el árbol de Vista.
La función del método de diseño es determinar la posición de la Vista en sí, es decir, establecer las posiciones de los cuatro vértices de la Vista, determinando así la posición de la Vista en el contenedor principal;
Método onLayout La función es para que el contenedor principal determine la posición del elemento secundario. Este método se implementa vacío en View porque View no tiene elementos secundarios. Está abstraído en ViewGroup y sus subclases deben implementarse. este método.
1. Dibuja el fondo ( background.draw(canvas);
2. Dibújate a ti mismo ( onDraw
3. Dibuja niños ( despachoDraw ); (lienzo));
4. Dibujar decoración (onDrawScrollBars).
El método despachoDraw se llama después del método onDraw, es decir, siempre se dibuja a sí mismo primero y luego dibuja la Vista secundaria.
Para la clase View, el método despachoDraw está vacío. Para la clase ViewGroup, el método despachoDraw tiene una implementación específica.
Pasado a través de despachoDraw.
despachoDraw atravesará y llamará al método de dibujo de los elementos secundarios, de modo que el evento de dibujo se pase capa por capa. despachoDraw se implementa vacío en la clase View y en realidad se implementa en la clase ViewGroup.
Si una Vista no necesita dibujar nada, establezca este indicador en verdadero y el sistema realizará una optimización adicional.
Cuando el control personalizado creado hereda de ViewGroup y no tiene la función de dibujo, puede activar esta etiqueta para facilitar la optimización posterior del sistema cuando está claro que un ViewGroup necesita dibujar contenido a través de onDraw; , es necesario desactivar esta marca.
Referencia: "Exploración del arte del desarrollo de Android"