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 de su vista personalizada de conocer cuáles son esas restricciones de diseño (en caso de que desee comportarse de manera diferente en una situación match_parent
que en una situación wrap_content
). Estas restricciones se empaquetan en los valores MeasureSpec
que se pasan al método. Aquí está una correlación aproximada de los valores del modo:
- exactamente significa el valor
layout_width
o layout_height
se establece en un valor específico. Probablemente deberías hacer tu vista de este tamaño. Esto también se puede activar cuando se usa match_parent
, para establecer el tamaño exactamente en la vista padre (esto depende del diseño en el marco).
- AT_MOST normalmente significa el valor
layout_width
o layout_height
se fijó a match_parent
o wrap_content
donde se necesita un tamaño máximo (esto es el diseño dependiente en el marco), y el tamaño de la dimensión de los padres es el valor. No deberías ser más grande que este tamaño.
- UNSPECIFIED normalmente significa el valor
layout_width
o layout_height
se fijó a wrap_content
sin restricciones. Puede ser del tamaño que desee. 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 de nuevo en una segunda solicitud de medida.
El contrato que existe con onMeasure()
es que setMeasuredDimension()
MUST se llamará al final con el tamaño que le gusta la vista que se va. Este método es invocado por todas las implementaciones de infraestructura, incluida la implementación predeterminada que se encuentra en View
, por lo que es seguro llamar a super
en su lugar, si corresponde a su caso de uso.
Otorgado, porque el marco aplica una implementación predeterminada, puede que no sea necesario que anule este método, pero puede ver el recorte en los casos en que el espacio de vista es menor que su contenido si no lo hace, y si usted diseña su vista personalizada con wrap_content
en ambas direcciones, ¡es posible que su vista no se muestre en absoluto porque el marco no sabe qué tan grande es!
general, si está sustituyendo View
y no otro widget existente, es probable que sea una buena idea para proporcionar una implementación, incluso si es tan simple como algo parecido a 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.
Hola @Devunwired buena explicación, la mejor que he leído hasta ahora. Tu explicación respondió muchas de las preguntas que tuve y despejó algunas dudas, pero aún queda una que es: si mi vista personalizada está dentro de un grupo de visualización junto con algunas otras vistas (no importa qué tipos) ese grupo de visualización obtendrá una ¿cada uno prueba su restricción de LayoutParams y le pide a cada niño que se mida a sí mismo de acuerdo con sus limitaciones? – pharaoh
Sí, eso es lo que hace el método 'measureChildren()' de 'ViewGroup' durante el proceso de medida/diseño. – Devunwired
Tenga en cuenta que este código no funcionará si anula onMeasure de cualquier subclase de ViewGroup. Sus subvistas no se mostrarán y todas tendrán un tamaño de 0x0. Si necesita sobrescribir en Measurement of a Custom ViewGroup, cambie widthMode, widthSize, heightMode y heightSize, compílelos de nuevo para measureSpecs utilizando MeasureSpec.makeMeasureSpec y pase los enteros resultantes a super.onMeasure. – Alexey