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_parentsituación que en una wrap_contentsituación). Estas restricciones se agrupan en los MeasureSpecvalores que se pasan al método. Aquí hay una correlación aproximada de los valores de modo:
- EXACTAMENTE significa que el valor
layout_widtho layout_heightse estableció en un valor específico. Probablemente debería hacer su vista de este tamaño. Esto también se puede activar cuando match_parentse 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_widtho layout_heightse estableció en match_parento wrap_contentdonde 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_widtho layout_heightse estableció wrap_contentsin 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 superen 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_contenten ambas direcciones, es posible que su vista no se muestre porque el marco no sabe qué tan grande es.
En general, si está anulando Viewy 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.