web-dev-qa-db-fra.com

Comment pouvez-vous savoir quand une mise en page a été dessinée?

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?

188
Plastic Sturgeon

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(); 

        } 
    });
376
blessenm

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(); 
    }
});
57
Elliptica

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();
            }
        });
21
murena

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
    }
});
3
jwehrle

Une autre réponse est:
Essayez de vérifier les dimensions de la vue en onWindowFocusChanged.

3
Joe Plante

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.
  }
});
2
Shivam Yadav

Lorsque onMeasure est appelée, la vue obtient sa largeur/hauteur mesurée. Ensuite, vous pouvez appeler layout.getMeasuredHeight().

1
Pavan