J'ai une vue personnalisée qui dessine un bitmap défilable à l'écran. Afin de l'initialiser, je dois passer la taille en pixels de l'objet physique parent. Mais lors des fonctions onCreate et onResume, la disposition n'a pas encore été dessinée et donc layout.getMeasuredHeight () renvoie 0.
Pour contourner le problème, j'ai ajouté un gestionnaire pour attendre une seconde, puis mesurer. Cela fonctionne, mais c'est bâclé, et je n'ai aucune idée de combien je peux réduire le temps avant de me retrouver avant que la mise en page ne soit dessinée.
Ce que je veux savoir, c'est comment puis-je détecter quand une mise en page est dessinée? Y a-t-il un événement ou un rappel?
Vous pouvez ajouter un observateur d'arborescence à la mise en page. Cela devrait retourner la largeur et la hauteur correctes. onCreate()
est appelé avant que la présentation des vues enfant ne soit terminée. Donc, la largeur et la hauteur ne sont pas encore calculées. Pour obtenir la hauteur et la largeur, mettez ceci sur la méthode onCreate()
:
final LinearLayout layout = (LinearLayout) findViewById(R.id.YOUR_VIEW_ID);
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener (new OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
layout.getViewTreeObserver()
.removeOnGlobalLayoutListener(this);
} else {
layout.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
}
int width = layout.getMeasuredWidth();
int height = layout.getMeasuredHeight();
}
});
Un moyen très simple consiste simplement à appeler post()
sur votre mise en page. Votre code sera exécuté à l’étape suivante, une fois votre vue créée.
YOUR_LAYOUT.post( new Runnable() {
@Override
public void run() {
int width = YOUR_LAYOUT.getMeasuredWidth();
int height = YOUR_LAYOUT.getMeasuredHeight();
}
});
Pour éviter le code obsolète et les avertissements, vous pouvez utiliser:
view.getViewTreeObserver().addOnGlobalLayoutListener(
new ViewTreeObserver.OnGlobalLayoutListener() {
@SuppressWarnings("deprecation")
@Override
public void onGlobalLayout() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
view.getViewTreeObserver()
.removeOnGlobalLayoutListener(this);
} else {
view.getViewTreeObserver()
.removeGlobalOnLayoutListener(this);
}
yourFunctionHere();
}
});
Une alternative aux méthodes habituelles consiste à accrocher le dessin de la vue.
OnPreDrawListener
est appelé plusieurs fois lors de l'affichage d'une vue. Il n'y a donc pas d'itération spécifique dans laquelle votre vue a une largeur ou une hauteur mesurée valide. Cela nécessite que vous vérifiiez continuellement (view.getMeasuredWidth() <= 0
) ou que vous limitiez le nombre de fois que vous recherchiez un measuredWidth
supérieur à zéro.
Il est également possible que la vue ne soit jamais dessinée, ce qui peut indiquer d'autres problèmes avec votre code.
final View view = [ACQUIRE REFERENCE]; // Must be declared final for inner class
ViewTreeObserver viewTreeObserver = view.getViewTreeObserver();
viewTreeObserver.addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
if (view.getMeasuredWidth() > 0) {
view.getViewTreeObserver().removeOnPreDrawListener(this);
int width = view.getMeasuredWidth();
int height = view.getMeasuredHeight();
//Do something with width and height here!
}
return true; // Continue with the draw pass, as not to stop it
}
});
Une autre réponse est:
Essayez de vérifier les dimensions de la vue en onWindowFocusChanged
.
Il suffit de vérifier en appelant la méthode post sur votre mise en page ou votre vue
view.post( new Runnable() {
@Override
public void run() {
// your layout is now drawn completely , use it here.
}
});
Lorsque onMeasure
est appelée, la vue obtient sa largeur/hauteur mesurée. Ensuite, vous pouvez appeler layout.getMeasuredHeight()
.