Dessiner des vues via Android

Lorsqu'un élément Activity est sélectionné, il est invité à dessiner sa mise en page. Le framework Android gère la procédure de dessin, mais l'élément Activity doit fournir le nœud racine de sa hiérarchie de mise en page.

Le dessin commence par le nœud racine de la mise en page. L'arborescence de mise en page doit être mesurée et dessinée. Le dessin est géré en parcourant l'arborescence et en affichant chaque View qui croise la région incorrecte. Chaque ViewGroup est responsable de la demande de dessin de chacun de ses enfants (avec la méthode draw()), et chaque View est responsable du dessin lui-même. Comme l'arborescence est balayée dans le sens inverse, les parents sont dessinés avant (ou derrière) leurs enfants, et les frères dans l'ordre dans lequel ils apparaissent dans l'arborescence.

Remarque : Le framework ne dessine pas d'objets View qui ne se trouvent pas dans une région valide. Il se charge également de dessiner l'arrière-plan View pour vous.

Vous pouvez forcer le dessin d'un élément View en appelant invalidate().

Le tracé de la mise en page s'effectue en deux étapes : une étape de mesure et une autre de mise en page.

Étape de mesure

La mesure est implémentée dans measure(int, int) et effectue un balayage de haut en bas de l'arborescence View. Chaque View transmet les spécifications de dimension vers le bas de l'arborescence pendant la récursion. À la fin de la mesure, chaque View a stocké ses mesures. La deuxième étape a lieu dans layout(int, int, int, int) et s'effectue également de haut en bas. Au cours de cette opération, chaque parent est responsable du positionnement de tous ses enfants à l'aide des tailles calculées dans l'étape de mesure.

Lorsque la méthode measure() d'un objet View est renvoyée, ses valeurs getMeasuredWidth() et getMeasuredHeight() doivent être définies, ainsi que celles qui correspondent à tous les descendants de cet objet View. Les valeurs de largeur et de hauteur mesurées d'un objet View doivent respecter les contraintes imposées par les parents de l'objet View. Cette approche garantit qu'à la fin de la mesure, tous les parents accepteront toutes les mesures de leurs enfants. Un parent View peut appeler measure() plusieurs fois pour ses enfants. Par exemple, le parent peut mesurer une fois chaque enfant avec des dimensions non spécifiées pour déterminer la taille qu'ils veulent avoir, puis appeler measure() pour les mesurer à nouveau avec des nombres réels si la somme de toutes les tailles non limitées des enfants est trop élevée ou trop faible (autrement dit, si les enfants ne parviennent pas à se mettre d'accord sur l'espace qu'ils occuperont chacun, le parent intervient et prend cette décision pour eux lors de deuxième étape).

La mesure utilise deux classes pour communiquer les dimensions. La classe ViewGroup.LayoutParams est utilisée par les objets View pour indiquer à leur parent comment ils souhaitent mesurer et positionner leurs données. La classe ViewGroup.LayoutParams de base décrit simplement la largeur et la hauteur souhaitées par l'élément View. Pour chaque dimension, elle peut spécifier l'une des valeurs suivantes :

  • Un nombre exact
  • MATCH_PARENT, ce qui signifie que View veut être aussi grand que son parent (moins la marge intérieure)
  • WRAP_CONTENT, ce qui signifie que View veut avoir la taille minimale suffisante pour accueillir son contenu (plus une marge intérieure)

Il existe des sous-classes de ViewGroup.LayoutParams pour différentes sous-classes de ViewGroup. Par exemple, RelativeLayout possède sa propre sous-classe de ViewGroup.LayoutParams, qui permet de centrer les objets enfants View horizontalement et verticalement.

Les objets MeasureSpec sont utilisés pour transmettre les exigences vers le bas de l'arborescence, du parent à l'enfant. Un élément MeasureSpec peut avoir l'un des trois modes suivants :

  • UNSPECIFIED : permet à un parent de déterminer la dimension souhaitée d'un élément View enfant. Par exemple, un élément LinearLayout peut appelermeasure() pour son enfant avec la hauteur définie sur UNSPECIFIED et une largeur de 240 "EXACTLY" pour déterminer la taille que l'élémentView enfant souhaite avoir pour une largeur de 240 pixels.
  • EXACTLY : valeur utilisée par le parent pour imposer une taille exacte à l'élément enfant. L'enfant doit utiliser cette taille et s'assurer que tous ses descendants s'adaptent à cette taille.
  • AT MOST : valeur utilisée par le parent pour imposer une taille maximale à l'enfant. L'enfant doit s'assurer que tous ses descendants et lui-même respectent cette taille.

Étape de mise en page

Pour initier une mise en page, appelez requestLayout(). Cette méthode est généralement appelée par un élément View qui estime qu'il ne peut plus tenir dans ses limites actuelles.