Faire qu'une vue remplisse une autre avec AutoLayout
Bonjour à tous,
Je cherche à faire quelque chose de très simple: faire en sorte qu'une vue enfant emplisse constamment sa vue parente. Constamment voulant dire, y compris après une rotation.
Voici comment je fais avec l'autoresizing mask:
ça fonctionne.
Ma question: Comment obtenir le même fonctionnement avec l'auto-layout?
Déjà , dans CardViewController.xib, je ne peux pas ajouter de contraintes à cardView.
J'ai essayé ça, mais une exception est lancée:
Ou alors, est-ce mon approche qui est totalement fausse ? Devrais-je ne pas ajouter cardView à cardPlaceHolderView, mais directement cardView dans la vue parente?
Je cherche à faire quelque chose de très simple: faire en sorte qu'une vue enfant emplisse constamment sa vue parente. Constamment voulant dire, y compris après une rotation.
Voici comment je fais avec l'autoresizing mask:
UIView *cardView = self.cardViewController.view;<br />
cardView.frame = CGRectMake(0.0f, 0.0f, self.cardPlaceholderView.frame.size.width, self.cardPlaceholderView.frame.size.height);<br />
[self.cardPlaceholderView addSubview:cardView];<br />
cardView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;<br />
ça fonctionne.
Ma question: Comment obtenir le même fonctionnement avec l'auto-layout?
Déjà , dans CardViewController.xib, je ne peux pas ajouter de contraintes à cardView.
J'ai essayé ça, mais une exception est lancée:
NSDictionary *viewDict = NSDictionaryOfVariableBindings(cardView);<br />
NSArray *constraints = [NSLayoutConstraint constraintsWithVisualFormat:@"V:|-0-[cardView]-0-|" options:0 metrics:nil views:viewDict];<br />
[cardView addConstraints:constraints];<br />
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to install constraint on view. Does the constraint reference something from outside the subtree of the view? That's illegal.
Ou alors, est-ce mon approche qui est totalement fausse ? Devrais-je ne pas ajouter cardView à cardPlaceHolderView, mais directement cardView dans la vue parente?
Mots clés:
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Je crois qu'Apple s'est fourvoyée sur ce coup là . On avait un système simple, avec une seule propriété autoResizingMask. On se retrouve avec 21 (!) nouvelles méthodes sur UIView, un Cocoa Auto Layout Guide, et un tas de nouveaux concepts dont on saisit mal l'enchevêtrement, même après visionné la vidéo de la WWDC. Je comprends le besoin, mais la solution me paraà®t incroyablement complexe.
@Jegnux:
OK, mais quelles contraintes? D'après ce que je vois dans la doc, les contraintes s'expriment plutôt par rapport aux vues parentes et aux vues soe“urs.
Pour ton cas ton VisualFormat est bon (bien que la forme plus compacte "|[cardView]|" sans les "-0-" serait aussi simple) mais il faut toujours associer une contrainte au parent commun à toutes les vues en présence, donc dans ton cas à ta vue parente de cardView et non à cardView elle-même. D'où l'exception.
De plus, n'oublie pas de désactiver la traduction automatique des autoresizingMasks existants en LayoutConstraints, car à partir du moment où tu utilises les contraintes sur une vue iOS va automatiquement tout traduire en contrainte, y compris les autoresizingMasks existants, ce qui est très pratique pour pouvoir faire une transition en douceur des autoresizingMasks vers les LayoutConstraints et pouvoir mélanger les deux (surtout si tu as une appli existante qui utilisait les AutoResizingMasks avant et que tu veux la migrer progressivement)... mais du coup si tu laisses ce fonctionnement pour ta vue à qui tu rajoutes des contraintes tu vas avoir tes contraintes + celles de l'AutoLayout qui vont se cumuler sur cette vue et vont entrer en conflit.
Donc il faudra utiliser [cardView setTranslatesAutoresizingMaskIntoConstraints:NO] pour éviter les conflits sur cette vue, sinon tu auras une exception (différente de ton actuelle) qui va te dire que tu as des "Insatisfiable Constraints".
Je t'invite à consulter la conf CocoaHeads de Rennes de Jeudi dernier où Thomas expliquait tout cela en détail ;-)
ISofTom vous préviendra sûrement quand ça sera dispo sinon ;-)
Via le storyboard c'est quand même un peu le bazard. On se retrouve vite avec 50.000 contraintes, qui se mettent toutes seules, parfois inutiles lorsqu'on a déplacé plusieurs fois certains éléments de l'interface.
Ne serait-ce qu'avoir une vue dans laquelle j'ai une tableView qui occupe une partie de l'écran qui s'agrandit pour remplir la place lorsqu'il s'agit d'un iPhone 5, je n'y arrive pas. Il faudra que je me plonge un jour vraiment dedans car c'est tout sauf intuitif.
Comme le disais Ali, mais que j'avais compris de travers ;-) si on ne veut pas d'ennui, il faut appeler setTranslatesAutoresizingMaskIntoConstraints:NO. J'ai pensé qu'à partir du moment où on disait que le XIB utilisait l'autolayout, c'était le cas. Je me trompais.
Si on le laisse à YES, des contraintes sont ajoutées automatiquement, et on obtient un message d'erreur disant qu'on ne peut satisfaire des contraintes antagonistes.
ça donne donc ceci: (avec une marge de 12 points):
Au départ, je n'avais fixé qu'une contrainte horizontale. La hauteur était mise à 0! Voilà qui me semble bien étrange. Ajouter une contrainte verticale semble donc nécessaire. En tout cas, ça fonctionne.
Merci Ali!
Et du coup si tu ne mets aucune contrainte verticale, c'est logique que la hauteur de ta vue n'étant ni spécifiée ni contrainte sera du coup égale à 0 /wink.png' class='bbc_emoticon' alt=';)' />
C'est vrai que la toute première fois qu'on voit AutoLayout on est un peu obligé de tomber dans les 2 pièges de base dans lesquels tu es tombé Céroce (ajouter les contraintes à la bonne vue + penser à désactiver la traduction des AutoResizingMask en LayoutConstraints pour éviter les conflits de contraintes.
Mais toutes les vidéos (surtout celles de la WWDC, très bien faites) expliquent ça en détail, et une fois qu'on est passé outre ces 2 points, cela devient assez propre et plus logique à comprendre.