Je suis un peu confus sur les rôles des forceLayout()
, requestLayout()
et des invalidate()
méthodes de la View
classe.
Quand seront-ils appelés?
Je suis un peu confus sur les rôles des forceLayout()
, requestLayout()
et des invalidate()
méthodes de la View
classe.
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 œil à ce superbe diagramme du cycle de vie des vues par Arpit Mathur :
TextView
. Je pensais qu'ils voulaient peut-être dessiner leView
pour la dernière fois avant de modifier ses paramètres liés à la mise en page, mais cela n'a pas vraiment de sens si nous pensons que ces appels sont invoqués dans un ordre différent (et ils appellentinvalidate()
juste aprèsrequestLayout()
dansTextView
ainsi que). Peut-être que cela mérite une autre question sur StackOverflow :)?invalidate()
etrequestLayout()
) correctement. Le but de ces méthodes est de direView
quelle sorte d' invalidation (comme vous l'avez appelée) s'est produite. Ce n'est pas comme si leView
décidait du chemin à suivre après avoir appelé l'une de ces méthodes. La logique derrière le choix duView
-lifecycle-path est le choix de la méthode appropriée pour s'appeler. S'il y a quelque chose lié au changement de taille -requestLayout()
devrait être appelé, s'il n'y a qu'un changement visuel sans changement de taille - vous devriez appelerinvalidate()
.View
d'une certaine manière, par exemple, vous obtenez le courantLayoutParams
de aView
et vous les modifiez, mais n'appelez PAS l' unrequestLayout
ou l' autresetLayoutParams
(qui appelle enrequestLayout
interne), alors vous pouvez appelerinvalidate()
autant que vous le souhaitez, et leView
ne passera pas par le processus de mise en page de la mesure et ne changera donc pas sa taille. Si vous ne dites pasView
que sa taille a changé (avec unrequestLayout
appel de méthode), alors leView
supposera que ce n'est pas le cas, et leonMeasure
etonLayout
ne sera pas appelé.invalidate()
L'appel
invalidate()
est effectué lorsque vous souhaitez planifier un rafraîchissement de la vue. Il en résulteraonDraw
éventuellement un appel (bientôt, mais pas immédiatement). Un exemple de quand une vue personnalisée l'appellerait est quand une propriété de couleur de texte ou d'arrière-plan a changé.La vue sera redessinée mais la taille ne changera pas.
requestLayout()
Si quelque chose dans votre vue change et affecte la taille, vous devez appeler
requestLayout()
. Cela déclencheraonMeasure
etonLayout
non seulement pour ce point de vue , mais tout le chemin jusqu'à la ligne pour les vues parent.Il
requestLayout()
n'est pas garanti qu'unonDraw
appel aboutisse à un (contrairement à ce que le diagramme de la réponse acceptée implique), il est donc généralement combiné avecinvalidate()
.Un exemple de ceci est lorsqu'une étiquette personnalisée voit sa propriété de texte modifiée. L'étiquette changerait de taille et devrait donc être remesurée et redessinée.
forceLayout()
Lorsqu'il y a un
requestLayout()
qui est appelé sur un groupe de vues parent, il n'est pas nécessaire de remesurer et de relayer ses vues enfants. Cependant, si un enfant doit être inclus dans la remesure et le relais, vous pouvez faire appelforceLayout()
à l'enfant.forceLayout()
ne fonctionne sur un enfant que s'il se produit en conjonction avec unrequestLayout()
sur son parent direct. L'appelforceLayout()
en lui-même n'aura aucun effet car il ne déclenche pas d'requestLayout()
arborescence de vues.Lisez ces questions et réponses pour une description plus détaillée de
forceLayout()
.Une étude plus approfondie
View
code sourcela source
requestLayout()
avantinvalidate()
si vous le souhaitez. Ni l'un ni l'autre ne fait de mise en page ou ne dessine immédiatement. Au contraire, ils définissent des drapeaux qui finiront par entraîner un relais et un redessiner.Ici vous pouvez trouver une réponse: http://developer.android.com/guide/topics/ui/how-android-draws.html
Pour moi, un appel à
invalidate()
actualise uniquement la vue et un appel àrequestLayout()
actualiser la vue et à calculer la taille de la vue à l'écran.la source
vous utilisez invalidate () sur une vue que vous souhaitez redessiner, il rendra son onDraw (Canvas c) invoqué, et requestLayout () effectuera à nouveau le rendu de la mise en page (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 comme les contraintes de la vue parent (par là, je veux dire que la hauteur ou la largeur du parent est WRAP_CONTENT et correspond donc à mesurer les enfants avant de pouvoir les envelopper à nouveau)
la source
Cette réponse n'est pas correcte
forceLayout()
.Comme vous pouvez le voir dans le code,
forceLayout()
il marque simplement la vue comme "nécessite un relais" mais il ne programme ni ne déclenche ce relais. Le relais ne se produira qu'à un moment donné dans le futur, le parent de la vue a été aménagé pour une autre raison.Il y a aussi un problème beaucoup plus important lors de l'utilisation
forceLayout()
etrequestLayout()
:Disons que vous avez appelé
forceLayout()
une vue. Désormais, lors de l'appelrequestLayout()
à un descendant de cette vue, Android appellera récursivementrequestLayout()
les ancêtres de ce descendant. Le problème est que cela arrêtera la récursion à la vue sur laquelle vous avez appeléforceLayout()
. Ainsi, l'requestLayout()
appel n'atteindra jamais la racine de la vue et ne planifiera donc jamais une passe de mise en page. Un sous-arbre entier de la hiérarchie de vues attend une mise en page et l'appelrequestLayout()
sur une vue de ce sous-arbre ne provoquera pas de mise en page. N'appeler querequestLayout()
sur n'importe quelle vue en dehors de ce sous-arbre rompra le charme.Je considérerais que l'implémentation de
forceLayout()
(et comment elle affecterequestLayout()
est cassée et vous ne devriez jamais utiliser cette fonction dans votre code.la source
View
et en rencontrant le problème moi-même et en le déboguant.forceLayout()
API: il ne force pas réellement une mise en page, mais change simplement un drapeau qui est observé dansonMeasure()
, maisonMeasure()
ne sera pas appelé à moinsrequestLayout()
qu'un explicite neView#measure()
soit appelé. Cela signifie que celaforceLayout()
devrait être associérequestLayout()
. D'un autre côté, pourquoi alors jouerforceLayout()
si j'ai encore besoin de jouerrequestLayout()
?requestLayout()
fait tout ce qui faitforceLayout()
aussi.forceLayout
sens. Donc, au final, c'est juste très mal nommé et documenté.invalidate()
--->onDraw()
depuis le fil de l'interface utilisateurpostInvalidate()
--->onDraw()
du fil d'arrière-planrequestLayout()
--->onMeasure()
etonLayout()
ET PAS nécessairementonDraw()
forceLayout()
--->onMeasure()
etonLayout()
JUST SI le parent direct a appelérequestLayout()
.la source