Je suis un peu confus quant aux rôles des méthodes forceLayout()
, requestLayout()
et invalidate()
de la classe View
.
Quand seront-ils appelés?
Pour mieux comprendre les réponses fournies par François BOURLIEUX et Dalvik , je vous suggère de jeter un coup d'œil à ce diagramme de cycle de vie de vue impressionnant réalisé par Arpit Mathur :
invalidate()
L'appel de invalidate()
est terminé lorsque vous souhaitez planifier un rafraîchissement de la vue. onDraw
sera appelé éventuellement (bientôt, mais pas immédiatement). Un exemple d'apparition d'une vue personnalisée est le cas où une propriété de couleur de texte ou d'arrière-plan a été modifiée.
La vue sera redessinée mais la taille ne changera pas.
requestLayout()
Si quelque chose change dans votre vue qui affectera la taille, appelez requestLayout()
. Cela déclenchera onMeasure
et onLayout
non seulement pour cette vue, mais tout le long de la ligne pour les vues parent.
L'appel de requestLayout()
est il n'est pas garanti que le résultat sera onDraw
(contrairement à ce que le diagramme de la réponse acceptée implique), il est donc généralement associé à invalidate()
.
invalidate();
requestLayout();
Un exemple de ceci est lorsqu'un libellé personnalisé a sa propriété text modifiée. L'étiquette changera de taille et devra donc être remesurée et redessinée.
forceLayout()
Lorsqu'il y a une requestLayout()
appelée sur un groupe de vues parent, il n'est pas nécessaire de réévaluer et de relayer ses vues enfants. Cependant, si un enfant doit être inclus dans la nouvelle mesure et la relance, vous pouvez appeler forceLayout()
sur l'enfant. forceLayout()
ne fonctionne sur un enfant que s'il est associé à une requestLayout()
sur son parent direct. L'appel de forceLayout()
seul n'aura aucun effet puisqu'il ne déclenche pas de requestLayout()
dans l'arborescence de la vue.
Lisez cette Q & A pour une description plus détaillée de forceLayout()
.
Ici, vous pouvez trouver une réponse: http://developer.Android.com/guide/topics/ui/how-Android-draws.html
Pour moi, un appel à invalidate()
ne rafraîchit que la vue et un appel à requestLayout()
rafraîchit la vue et calcule la taille de la vue à l'écran.
si vous utilisez invalidate () sur une vue que vous souhaitez redessiner, elle invoquera son onDraw (Canvas c) et requestLayout () fera de nouveau exécuter le rendu complet de la présentation (phase de mesure et phase de positionnement). Vous devez l'utiliser si vous modifiez la taille de la vue enfant au moment de l'exécution, mais uniquement dans des cas particuliers, tels que les contraintes de la vue parent (j'entends par là que la hauteur ou la largeur du parent est WRAP_CONTENT et correspond donc à la mesure des enfants avant qu'ils ne puissent les envelopper à nouveau)
Cette réponse n'est pas correct à propos de forceLayout()
.
Comme vous pouvez le voir dans le code de forceLayout()
, il marque simplement la vue comme "nécessite un relais", mais ne planifie ni ne déclenche ce relais. La retransmission ne se fera pas avant que le parent de la vue ait été aménagé pour une autre raison.
Il y a également un problème beaucoup plus important lors de l'utilisation de forceLayout()
et requestLayout()
:
Disons que vous avez appelé forceLayout()
sur une vue. Désormais, lors de l'appel de requestLayout()
sur un descendant de cette vue, Android appellera récursivement _ requestLayout()
sur les ancêtres de ce descendant. Le problème est que cela arrêtera la récursion sur la vue sur laquelle vous avez appelé forceLayout()
. Ainsi, l'appel requestLayout()
n'atteindra jamais la racine de la vue et ne planifiera donc jamais une passe de présentation. Un sous-arbre complet de la hiérarchie des vues attend une mise en page et l'appel de requestLayout()
sur une vue de cette sous-arborescence ne provoquent pas de mise en page. Appeler uniquement requestLayout()
sur une vue en dehors de cette sous-arborescence annulera le sort.
Je considérerais que l'implémentation de forceLayout()
(et comment cela affecte requestLayout()
est cassé et vous ne devriez jamais utiliser cette fonction dans votre code.