Le problème de base est que vous devez attendre la phase de dessin pour les mesures réelles (en particulier avec des valeurs dynamiques comme wrap_content
ou match_parent
), mais généralement cette phase n'est pas terminée onResume()
. Vous avez donc besoin d'une solution de contournement pour attendre cette phase. Il existe différentes solutions possibles à cela:
1. Écoutez les événements Draw / Layout: ViewTreeObserver
Un ViewTreeObserver est déclenché pour différents événements de dessin. Habituellement, OnGlobalLayoutListener
c'est ce que vous voulez pour obtenir la mesure, donc le code dans l'auditeur sera appelé après la phase de mise en page, donc les mesures sont prêtes:
view.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
view.getViewTreeObserver().removeOnGlobalLayoutListener(this);
view.getHeight(); //height is ready
}
});
Remarque: l'écouteur sera immédiatement supprimé car sinon, il se déclenchera à chaque événement de mise en page. Si vous devez prendre en charge les applications SDK Lvl <16, utilisez-le pour désinscrire l'auditeur:
public void removeGlobalOnLayoutListener (ViewTreeObserver.OnGlobalLayoutListener victim)
2. Ajoutez un exécutable à la file d'attente de mise en page: View.post ()
Pas très connu et ma solution préférée. Fondamentalement, utilisez simplement la méthode de publication de View avec votre propre exécutable. Cela met essentiellement votre code en file d'attente après la mesure, la disposition, etc. de la vue, comme indiqué par Romain Guy :
La file d'attente d'événements de l'interface utilisateur traitera les événements dans l'ordre. Une fois que setContentView () est invoqué, la file d'attente d'événements contiendra un message demandant une sortie relais, donc tout ce que vous publierez dans la file d'attente se produira après le passage de la mise en page
Exemple:
final View view=//smth;
...
view.post(new Runnable() {
@Override
public void run() {
view.getHeight(); //height is ready
}
});
L'avantage sur ViewTreeObserver
:
- votre code n'est exécuté qu'une seule fois et vous n'avez pas à désactiver l'observateur après l'exécution, ce qui peut être un problème
- syntaxe moins verbeuse
Références:
3. Écraser la méthode onLayout des vues
Ceci n'est pratique que dans certaines situations où la logique peut être encapsulée dans la vue elle-même, sinon c'est une syntaxe assez bavarde et encombrante.
view = new View(this) {
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
super.onLayout(changed, l, t, r, b);
view.getHeight(); //height is ready
}
};
Sachez également que onLayout sera appelé plusieurs fois, alors pensez à ce que vous faites dans la méthode ou désactivez votre code après la première fois
4. Vérifiez si la phase de mise en page a été franchie
Si vous avez du code qui s'exécute plusieurs fois lors de la création de l'interface utilisateur, vous pouvez utiliser la méthode de support v4 lib suivante:
View viewYouNeedHeightFrom = ...
...
if(ViewCompat.isLaidOut(viewYouNeedHeightFrom)) {
viewYouNeedHeightFrom.getHeight();
}
Renvoie true si la vue a traversé au moins une disposition depuis sa dernière connexion ou déconnexion à une fenêtre.
Supplémentaire: Obtention de mesures définies statiquement
S'il suffit juste d'obtenir la hauteur / largeur définie statiquement, vous pouvez simplement le faire avec:
Mais attention, cela peut être différent de la largeur / hauteur réelle après le dessin. Le javadoc décrit parfaitement la différence:
La taille d'une vue est exprimée avec une largeur et une hauteur. Une vue possède en réalité deux paires de valeurs de largeur et de hauteur.
La première paire est connue sous le nom de largeur et hauteur mesurées. Ces dimensions définissent la taille d'une vue au sein de son parent (voir Présentation pour plus de détails.) Les dimensions mesurées peuvent être obtenues en appelant getMeasuredWidth () et getMeasuredHeight ().
La deuxième paire est simplement appelée largeur et hauteur, ou parfois largeur et hauteur de dessin. Ces dimensions définissent la taille réelle de la vue à l'écran, au moment du dessin et après la mise en page. Ces valeurs peuvent, mais ne doivent pas nécessairement, être différentes de la largeur et de la hauteur mesurées. La largeur et la hauteur peuvent être obtenues en appelant getWidth () et getHeight ().