onMeasure()
est l'occasion pour vous d'indiquer à Android la taille de votre vue personnalisée en fonction des contraintes de mise en page fournies par le parent ; c'est également l'occasion pour votre vue personnalisée d'apprendre quelles sont ces contraintes de mise en page (au cas où vous voudriez vous comporter différemment dans une match_parent
situation qu'une wrap_content
situation). Ces contraintes sont regroupées dans le MeasureSpec
qui sont transmises à la méthode. Voici une corrélation approximative des valeurs de la méthode :
-
EXACTEMENT signifie que
layout_width
o layout_height
a été fixé à une valeur spécifique. Vous devriez probablement donner à votre vue cette taille. Ceci peut également être déclenché lorsque match_parent
est utilisé pour définir la taille exacte de la vue parent (cela dépend de la mise en page dans le cadre).
-
AT_MOST signifie généralement que le
layout_width
o layout_height
a été fixé à match_parent
o wrap_content
où une taille maximale est nécessaire (cela dépend de la disposition dans le cadre), et la taille de la dimension parent est la valeur. Vous ne devez pas dépasser cette taille.
-
NON SPÉCIFIÉ signifie généralement que le
layout_width
o layout_height
a été fixé à wrap_content
sans aucune restriction. Vous pouvez être de la taille que vous souhaitez. Certaines mises en page utilisent également ce rappel pour déterminer votre taille souhaitée avant de déterminer les spécifications à vous passer à nouveau dans une deuxième demande de mesure.
Le contrat qui existe avec onMeasure()
c'est que setMeasuredDimension()
MUST être appelé à la fin avec la taille que vous souhaitez pour la vue. Cette méthode est appelée par toutes les implémentations du framework, y compris l'implémentation par défaut trouvée dans le fichier View
c'est pourquoi il est prudent d'appeler super
à la place, si cela correspond à votre cas d'utilisation.
Bien sûr, comme le framework applique une implémentation par défaut, il n'est peut-être pas nécessaire de remplacer cette méthode, mais vous risquez de voir des coupures dans les cas où l'espace de la vue est plus petit que votre contenu si vous ne le faites pas, et si vous disposez votre vue personnalisée avec wrap_content
dans les deux sens, il se peut que votre vue n'apparaisse pas du tout car le cadre ne sait pas quelle est sa taille !
En général, si vous remplacez View
et pas un autre widget existant, c'est probablement une bonne idée de fournir une implémentation, même si c'est aussi simple que quelque chose comme ceci :
@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);
}
J'espère que cela vous aidera.