web-dev-qa-db-fra.com

Disposition et dimensionnement des sous-vues dans un UIViewController

J'ai une application avec un UITabController et chaque onglet est un UINavigationController. La racine de l'un de mes UINavigationControllers est un UIViewController.

Dans la vue de ce contrôleur de vue, je veux mettre en page certaines sous-vues, mais je ne sais pas où et comment les disposer d'une manière qui sera indépendante de la résolution (c'est-à-dire pas des valeurs de code dur telles que 320px, 480px, 44px, etc. ).

Lorsque la vue est entièrement chargée et présentée sur un iPhone vertical, sa hauteur sera de 367 pixels = 480 - 20 (barre d'état) - 44 (barre de navigation) - 49 (barre d'onglets).

À l'intérieur du contrôleur de vue, je crée actuellement toutes mes sous-vues dans la méthode viewDidLoad. Cependant, il semble que dans cette méthode, la hauteur actuelle de la vue est de 460 pixels (self.view.bounds.size.height). Donc, lors de la configuration de mes sous-vues, je ne peux pas calculer correctement les tailles de quoi que ce soit.

Dans le viewWillAppear: méthode, la vue sait sait que sa taille est correcte, mais cela signifierait définir et calculer les cadres de la sous-vue chaque fois que la vue apparaîtra (par exemple, les changements de tabulation ou le saut des contrôleurs de vue enfant sur la pile de navigation).

Est le seul moyen de procéder correctement à la mise en page dans viewWillAppear:?

J'ai essayé d'utiliser les propriétés de redimensionnement automatique (autoresizesSubviews & autoresizingMask) des parents, mais elles ne semblent pas fonctionner du tout!? Celles-ci ne prennent effet que lorsque la vue est entièrement configurée, puis redimensionnée (manuellement/changement d'orientation?).

Je serais reconnaissant si quelqu'un pouvait me faire savoir pourquoi le redimensionnement automatique ne fonctionne pas et comment mieux organiser les choses en ne codant en dur aucune taille.

49
Michael Waterfall

autoresizesSubviews doit être défini sur votre vue parent, tandis que autoresizingMask doit être défini sur les vues enfant - c'est l'erreur que j'ai commise, vous le pouvez aussi.

Dans loadView, vous devez dimensionner vos sous-vues pour qu'elles correspondent à la taille actuelle de la vue parent, puis plus tard, lorsque la vue parent sera redimensionnée de 460 à 367 pixels, vos sous-vues seront également redimensionnées, selon vos paramètres de masque ci-dessus.

Si cela échoue, il n'y a rien de mal à définir la taille de la vue dans viewWillAppear - l'impact sur les performances de le faire à chaque fois est négligeable.

Si rien d'autre ne fonctionne, il y a toujours layoutSubviews: - là, vous pouvez faire une mise en page manuelle si vous le devez, elle est invoquée lorsque le système pense que la mise en page peut devoir changer. il y a aussi setNeedsLayout: que j'invoque parfois depuis viewWillRotate:/viewDidRotate: etc. Mais cela ne devrait vraiment pas être nécessaire et le redimensionnement automatique devrait être suffisant.

EDIT: Oui, pour implémenter une logique de disposition personnalisée dans layoutSubviews comme je le mentionne ci-dessus, il faudrait sous-classer UIView.

35
DenNukem

Vous pouvez faire votre logique de disposition dans le viewWillLayoutSubviews du UIViewController.

-(void)viewWillLayoutSubviews{
    [super viewWillLayoutSubviews];
    // Your layout logic here
}

DOC: appelé juste avant l'appel de la méthode layoutSubviews du contrôleur de vue. Les sous-classes peuvent être implémentées si nécessaire. La valeur par défaut est un nop.

43
aumanets