Utilisation de forceLayout (), requestLayout () et invalidate()

je suis un peu confus au sujet des rôles de forceLayout() , requestLayout() et invalidate() méthodes de la classe View .

quand seront-ils appelés?

137
demandé sur fiddler 2012-12-13 12:55:05

5 réponses

pour mieux comprendre les réponses fournies par François BOURLIEUX et Dalvik je vous suggère de jeter un oeil à ce diagramme du cycle de vie vue impressionnante par Arpit Mathur : enter image description here

280
répondu Bartek Lipinski 2017-05-23 12:34:53

invalidate()

appelant invalidate() est fait quand vous voulez programmer un nouveau dessin de la vue. Il en résultera que onDraw sera finalement 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é.

Le point de vue sera redessiné, mais la taille ne change pas.

requestLayout()

si quelque chose au sujet de votre vue change qui affectera la taille, alors vous devriez appeler requestLayout() . Cela déclenchera onMeasure et onLayout non seulement pour cette vue mais tout le long de la ligne pour les vues parentes.

appeler requestLayout() est ne garantit pas d'aboutir à un onDraw (contrairement à ce que le diagramme dans la réponse acceptée implique), il est donc généralement combiné avec invalidate() .

invalidate();
requestLayout();

Un exemple de ceci est quand une étiquette personnalisée a sa propriété text changé. 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 vue de parent, il n'est pas nécessaire de réévaluer et de relayer ses points de vue d'enfant. Cependant, si un enfant doit être inclus dans le réévaluer et relayout, ensuite vous pouvez appeler forceLayout() sur l'enfant. forceLayout() ne fonctionne sur un enfant que si elle se produit en conjonction avec un requestLayout() sur son parent direct. Appeler forceLayout() par lui-même n'aura aucun effet puisqu'il ne déclenche pas un requestLayout() dans l'arbre de la vue.

lisez cette Q&R pour une description plus détaillée de forceLayout() .

complément d'étude

78
répondu Suragch 2017-10-20 03:27:17

Ici vous pouvez trouver une réponse: http://developer.android.com/guide/topics/ui/how-android-draws.html

pour moi un appel à invalidate() rafraîchit seulement la vue et un appel à requestLayout() rafraîchit la vue et calcule la taille de la vue sur l'écran.

25
répondu François BOURLIEUX 2017-07-27 04:02:21

vous utilisez invalidate() sur une vue que vous voulez redessiner, il va faire son onDraw(Canvas c) à invoquer, et requestLayout() va faire redémarrer l'ensemble du rendu de la mise en page ( Phase de mesure et phase de positionnement). Vous devriez l'utiliser si vous changez la taille de la vue enfant sur l'exécution mais seulement dans des cas particuliers comme les contraintes de la vue parent(par cela je veux dire que la taille ou la largeur de parent sont WRAP_CONTENT et ainsi match mesurer les enfants avant qu'ils ne puissent les envelopper à nouveau)

3
répondu Nativ 2016-10-23 11:20:16

Cette réponse n'est pas correct sur forceLayout() .

comme vous pouvez le voir dans le code de forceLayout() il marque simplement la vue comme" a besoin d'un relayout", mais il ne prévoit ni ne déclenche que relayout. Le relayout ne se produira pas jusqu'à ce qu'à un certain point dans l'avenir le parent de la vue a été exposé pour une autre raison.

il y a aussi un problème beaucoup plus important lors de l'utilisation de forceLayout() et requestLayout() :

disons que vous avez appelé forceLayout() sur une vue. Maintenant, en appelant requestLayout() sur un descendant de cette vue, Android va récursivement appeler requestLayout() sur les ancêtres de ce descendant. Le problème est qu'il va arrêter la récursion à la vue sur laquelle vous avez appelé forceLayout() . ainsi l'appel requestLayout() n'atteindra jamais la racine de la vue et donc ne planifiera jamais un passage de layout. un sous-arbre entier de la hiérarchie de vue est attendre une mise en page et appeler requestLayout() sur n'importe quelle vue de ce sous-arbre ne provoquera pas une mise en page. Appeler requestLayout() sur n'importe quelle vue en dehors de ce sous-arbre va briser le sort.

je considérerais que la mise en œuvre de forceLayout() (et comment elle affecte requestLayout() d'être cassé et vous ne devriez jamais utiliser cette fonction dans votre code.

1
répondu fluidsonic 2017-10-21 05:38:58