Question

J'ai une vue personnalisée qui n'est pas de recevoir des messages de layoutSubview pendant l'animation.

J'ai une vue qui remplit l'écran. Il a une sous-vue personnalisé au bas de l'écran qui redimensionne correctement dans Interface Builder si je change la hauteur de la barre de navigation. layoutSubviews est appelée lorsque la vue est créée, mais jamais à nouveau. Mes subviews sont posés correctement. Si je bascule l'appel en barre d'état au large, n'est pas appelé le layoutSubviews du sous-vue du tout, même si la vue principale ne d'animer Redimensionner.

Dans quelles circonstances est layoutSubviews effectivement appelé?

Je autoresizesSubviews mis à NO pour mon affichage personnalisé. Et dans Interface Builder je le haut et en bas et jambes de force l'ensemble flèche verticale.


Une autre partie du casse-tête est que la fenêtre doit être clé:

[window makeKeyAndVisible];

d'autre les sous-vues ne sont pas automatiquement redimensionnées.

Était-ce utile?

La solution 5

Je pisté la solution jusqu'à l'insistance d'Interface Builder que les sources ne peuvent pas être modifiés sur une vue qui a les éléments d'écran simulé sous tension (barre d'état, etc.). Étant donné que les sources étaient hors de la vue principale, ce point de vue ne pouvait pas changer la taille et donc défilait dans son intégralité lorsque la barre en appel est apparu.

Pour activer les fonctions simulées hors tension, puis redimensionner la vue et le réglage des ressorts correctement causé l'animation de se produire et ma méthode à appeler.

Un problème supplémentaire dans le débogage est que le simulateur quitte l'application lorsque l'état en appel est activée via le menu. Quitter app = pas débogueur.

Autres conseils

J'avais une question similaire, mais n'a pas été satisfait de la réponse (ou tout ce que je pouvais trouver sur le net), donc je l'ai essayé dans la pratique et est ici ce que je suis:

  • init ne cause pas à layoutSubviews être appelé (duh)
  • causes addSubview: layoutSubviews à appeler le vue ajoutée, la vue, il est d'être ajouté à (voir la cible), et tout le subviews de la cible
  • vue
  • setFrame appelle intelligemment sur layoutSubviews la vue ayant son cadre défini que si le paramètre de taille de la trame est différent
  • un défilement UIScrollView les causes layoutSubviews à être appelés le ScrollView, et son superview
  • rotation un dispositif uniquement les appels layoutSubview sur la vue parent ( viewControllers primaire répondant vue)
  • Redimensionnement une vue appellera layoutSubviews sur son superview

Mes résultats - http: // blog. logichigh.com/2011/03/16/when-does-layoutsubviews-get-called/

Miser sur la réponse précédente @BadPirate, j'ai expérimenté un peu plus loin et est venu avec quelques éclaircissements / corrections. Je trouve que layoutSubviews: sera appelé une vue si et seulement si:

  • Ses propres limites (cadre non) ont changé.
  • Les limites de l'un de ses sous-vues directes ont changé.
  • A sous-vue est ajouté à la vue ou retiré de la vue.

Quelques détails pertinents:

  • Les limites sont considérées comme modifiées que si la nouvelle valeur est différente, y compris une autre origine . Notez précisément c'est pourquoi layoutSubviews: est appelée chaque fois qu'un défile UIScrollView, car il effectue le défilement en changeant l'origine de ses limites.
  • Modification du cadre ne change les limites si la taille a changé, car cela est la seule chose propagée à la propriété bounds.
  • Un changement dans les limites d'une vue qui ne sont pas encore dans une hiérarchie de vue se traduira par un appel à layoutSubviews: lorsque la vue est finalement ajouté à une hiérarchie de vue .
  • Et pour être complet: ces déclencheurs ne le font pas directement appeler layoutSubviews, mais plutôt appeler setNeedsLayout, qui fixe / lève un drapeau. Chaque itération de la boucle d'exécution, pour toutes les vues dans la hiérarchie de la vue , ce drapeau est cochée. Pour chaque vue où le drapeau est trouvé levé, layoutSubviews: est appelé et le drapeau est remis à zéro. Vues plus haut dans la hiérarchie seront vérifiés / appelé en premier.

https://developer.apple.com/library/prerelease/tvos/documentation/WindowsViews/Conceptual/ViewPG_iPhoneOS/CreatingViews/CreatingViews.html#//apple_ref/doc/uid/TP40009503-CH5- SW1

  

changements de mise en page peuvent se produire lorsque l'un des événements suivants se produit   en vue:

     

a. La taille des changements de rectangle de limites d'une vue.
  b. Un changement d'orientation de l'interface se produit, ce qui déclenche généralement un changement dans le rectangle des limites de la vue racine.
  c. L'ensemble des sous-couches d'animation de base associés aux changements de la couche de la vue et nécessite la mise en page.
  ré. Vos forces d'application mise en page se produire en appelant la méthode setNeedsLayout ou layoutIfNeeded d'une vue.
  e. Vos forces d'application mise en page en appelant la méthode setNeedsLayout d'objet de couche sous-jacente de la vue.

Certains des points de réponse de BadPirate ne sont que partiellement vrai:

  1. Pour le point de addSubView

      

    addSubview fait layoutSubviews à appeler à la vue étant ajoutée, la vue, il est ajouté à (vue cible), et tous les sous-vues de la cible.

    Cela dépend (vue cible) masque de redimensionnement automatique de la vue. Si elle a autoresize masque, layoutSubview sera appelé à chaque addSubview. Si elle n'a pas de masque autoresize alors layoutSubview sera appelée que lorsque la taille cadre (cible) Voir de la vue change.

    Exemple: si vous avez créé UIView programme (il n'a pas de masque autoresize par défaut), LayoutSubview sera appelée que lorsque le cadre UIView ne change pas sur tous les addSubview

    .

    Il est par cette technique que la performance de l'application augmente également.

  2. Pour le point de rotation de l'appareil

      

    La rotation d'un dispositif appelle uniquement layoutSubview sur la vue parent (la vue principale de répondre viewController)

    Cela peut être vrai que lorsque votre CV est dans la hiérarchie VC (racine à window.rootViewController), ce bien est le cas le plus courant. Dans iOS 5, si vous créez un CV, mais il est pas ajouté dans une autre VC, alors ce VC n'obtiendrait pas remarqué quand rotate de l'appareil. Par conséquent, son point de vue ne serait pas se faire remarquer en appelant layoutSubviews.

appel [self.view setNeedsLayout]; en viewController fait appeler viewDidLayoutSubviews

Avez-vous regardé layoutIfNeeded?

L'extrait de la documentation est ci-dessous. Est-ce que le travail d'animation si vous appelez cette méthode explicitement lors de l'animation?

layoutIfNeeded Expose les sous-vues si nécessaire.

- (void)layoutIfNeeded

Discussion Utilisez cette méthode pour forcer la mise en page des sous-vues avant de tirer.

Disponibilité Disponible dans l'iPhone OS 2.0 et versions ultérieures.

Lors de la migration d'une application OpenGL du SDK 3 à 4, layoutSubviews n'a pas été appelé plus. Après beaucoup d'essais et d'erreurs j'ai finalement ouvert MainWindow.xib, sélectionné l'objet de la fenêtre, dans l'inspecteur a choisi la fenêtre onglet Attributs (à gauche) et vérifié « Visible au lancement ». Il semble que dans SDK 3 il encore utilisé pour faire un appel layoutSubviews, mais pas 4.

6 heures de frustration mis fin.

Un cas assez obscure, mais potentiellement important quand layoutSubviews ne fait jamais appelé est:

import UIKit

class View: UIView {

    override class var layerClass: AnyClass { return Layer.self }

    class Layer: CALayer {
        override func layoutSublayers() {
            // if we don't call super.layoutSublayers()...
            print(type(of: self), #function)
        }
    }

    override func layoutSubviews() {
        // ... this method never gets called by the OS!
        print(type(of: self), #function)
    }
}

let view = View(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top