onMeasure()
es su oportunidad de decirle a Android qué tan grande quiere que su vista personalizada dependa de las restricciones de diseño proporcionadas por el padre; también es la oportunidad de su vista personalizada para aprender cuáles son esas restricciones de diseño (en caso de que desee comportarse de manera diferente en una match_parent
situación que en una wrap_content
situación). Estas restricciones se agrupan en los MeasureSpec
valores que se pasan al método. Aquí hay una correlación aproximada de los valores de modo:
- EXACTAMENTE significa que el valor
layout_width
o layout_height
se estableció en un valor específico. Probablemente debería hacer su vista de este tamaño. Esto también se puede activar cuando match_parent
se usa, para establecer el tamaño exactamente en la vista principal (esto depende del diseño en el marco).
- AT_MOST generalmente significa que el valor
layout_width
o layout_height
se estableció en match_parent
o wrap_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 debe ser más grande que este tamaño.
- NO ESPECIFICADO normalmente significa que el valor
layout_width
o layout_height
se estableció wrap_content
sin restricciones. Puedes ser del tamaño que quieras. Algunos diseños también usan esta devolución de llamada para determinar el tamaño deseado antes de determinar qué especificaciones realmente le pasarán nuevamente en una solicitud de segunda medida.
El contrato que existe onMeasure()
es que setMeasuredDimension()
DEBE llamarse al final con el tamaño que le gustaría que fuera la vista. Todas las implementaciones de framework llaman a este método, incluida la implementación predeterminada que se encuentra en View
, por lo que es seguro llamar super
en su lugar si se ajusta a su caso de uso.
De acuerdo, dado que el marco aplica una implementación predeterminada, puede que no sea necesario que anule este método, pero puede ver recorte en los casos en que el espacio de visualización sea más pequeño que su contenido si no lo hace, y si diseña su vista personalizada con wrap_content
en ambas direcciones, es posible que su vista no se muestre porque el marco no sabe qué tan grande es.
En general, si está anulando View
y no otro widget existente, probablemente sea una buena idea proporcionar una implementación, incluso si es tan simple como algo 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.