android - usar - onMeasure explicación personalizada de la vista
el celular te puede dejar ciego (2)
en realidad, su respuesta no está completa ya que los valores también dependen del contenedor de envoltura. En el caso de diseños relativos o lineales, los valores se comportan así:
- EXACTAMENTE match_parent es EXACTAMENTE + el tamaño del padre
- AT_MOST wrap_content da como resultado un AT_MOST MeasureSpec
- NO ESPECIFICADO nunca activado
En el caso de una vista de desplazamiento horizontal, su código funcionará.
Intenté hacer componente personalizado. onDraw
clase View
y hice algunos dibujos en el método onDraw
de onDraw
. ¿Por qué necesito anular onMeasure
? Si no lo hice, todo lo visto es correcto. ¿Puede alguien explicarlo? ¿Cómo debo escribir mi método onMeasure
? He visto un par de tutoriales, pero cada uno es un poco diferente al otro. A veces llaman super.onMeasure
al final, a veces usan setMeasuredDimension
y no lo llaman. ¿Dónde hay una diferencia?
Después de todo quiero usar varios exactamente los mismos componentes. Agregué esos componentes a mi archivo XML
, pero no sé qué tan grandes deberían ser. Quiero establecer su posición y tamaño más adelante (por eso necesito establecer el tamaño en onMeasure
si en onDraw
cuando lo dibuje, también funciona) en la clase de componente personalizado. ¿Cuándo exactamente necesito hacer eso?
onMeasure()
es su oportunidad de decirle a Android qué tan grande desea que su vista personalizada dependa de las restricciones de diseño proporcionadas por el padre; También es la oportunidad que tiene su vista personalizada de aprender cuáles son esas restricciones de diseño (en caso de que quiera comportarse de manera diferente en una situación match_parent
que en una situación wrap_content
). Estas restricciones se empaquetan en los valores de MeasureSpec
que se pasan al método. Aquí hay una correlación aproximada de los valores de modo:
- EXACTAMENTE significa que el valor de
layout_width
olayout_height
se estableció en un valor específico. Probablemente debería hacer su vista de este tamaño. Esto también puedematch_parent
cuando se usamatch_parent
, para establecer el tamaño exactamente en la vista principal (esto depende del diseño en el marco). - AT_MOST normalmente significa que el valor
layout_width
olayout_height
se estableció enmatch_parent
owrap_content
donde se necesita un tamaño máximo (esto depende del diseño en el marco), y el tamaño de la dimensión principal es el valor. No debes ser más grande que este tamaño. - Normalmente, UNSPECIFIED significa que el valor
layout_width
olayout_height
se estableció enwrap_content
sin restricciones. Puedes ser del tamaño que quieras. Algunos diseños también usan esta devolución de llamada para averiguar su tamaño deseado antes de determinar qué especificaciones realmente le pasan de nuevo en una segunda solicitud de medida.
El contrato que existe con onMeasure()
es que setMeasuredDimension()
DEBE llamarse al final con el tamaño que desea que tenga la vista. Este método es llamado por todas las implementaciones de la infraestructura, incluida la implementación predeterminada que se encuentra en la View
, por lo que es seguro llamar a super
en su lugar si se ajusta a su caso de uso.
Por supuesto, dado que el marco aplica una implementación predeterminada, puede que no sea necesario que sustituya este método, pero puede ver recortes en los casos en que el espacio de visualización sea más pequeño que su contenido si no lo hace, y si presenta su vista personalizada con wrap_content
en ambas direcciones, puede que su vista no se muestre en absoluto porque el marco no sabe qué tan grande es.
En general, si está anulando la View
y no otro widget existente, probablemente sea una buena idea proporcionar una implementación, incluso si es tan simple como esto:
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
int desiredWidth = 100;
int desiredHeight = 100;
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = MeasureSpec.getSize(widthMeasureSpec);
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = MeasureSpec.getSize(heightMeasureSpec);
int width;
int height;
//Measure Width
if (widthMode == MeasureSpec.EXACTLY) {
//Must be this size
width = widthSize;
} else if (widthMode == MeasureSpec.AT_MOST) {
//Can''t be bigger than...
width = Math.min(desiredWidth, widthSize);
} else {
//Be whatever you want
width = desiredWidth;
}
//Measure Height
if (heightMode == MeasureSpec.EXACTLY) {
//Must be this size
height = heightSize;
} else if (heightMode == MeasureSpec.AT_MOST) {
//Can''t be bigger than...
height = Math.min(desiredHeight, heightSize);
} else {
//Be whatever you want
height = desiredHeight;
}
//MUST CALL THIS
setMeasuredDimension(width, height);
}
Espero que ayude.