J'ai passé deux jours à essayer les différentes solutions pour les approches de mise en page automatique mixte et pure pour réaliser ce qui était une configuration triviale de scrollview avant la mise en page automatique, et c'est maintenant officiel - je dois être trop stupide. Je mets cela en place principalement dans Storyboard (enfin, c'est juste comme ça).
Alors, voici mon appel à l'aide.
Viewtree:
UIView
-UIView
-UIView
..-UIScrollview
...-UIButton
...-UIButton
...-UIButton
Les boutons sont censés défiler horizontalement (de gauche à droite et vice versa). Quelqu'un peut-il s'il vous plaît me faire savoir comment définir les contraintes pour y parvenir en utilisant pure Autolayout ???
-
J'ai essayé l'approche mixte, comme ceci:
UIView
- UIView
- UIView
..-UIScrollview
...-UIView (contentview)
....-UIButton
....-UIButton
....-UIButton
... et définir des contraintes de largeur et de hauteur fixes pour le contentview
et les translatesAutoresizingMaskIntoConstraints
paramètres conformément à la note technique d'Apple. Les boutons et la vue de défilement sont configurés à l'aide de contraintes. Cela fait défiler la vue de défilement (yay) mais hélas, ça défile trop loin! Pour autant que je sache, la largeur du défilement est en quelque sorte doublée par rapport à ce que j'ai défini pour la vue de contenu ??? !!! ???
J'ai également essayé l'approche de mise en page automatique pure, avec contentview
et sans. Toutes les vues sont translatesAutoresizingMaskIntoConstraints=NO
, sauf pour self.view
. Les boutons ont des contraintes de largeur / hauteur fixes et sont épinglés aux quatre bords de la vue de défilement. Rien ne défile.
Je suis donc totalement perplexe de savoir pourquoi je ne peux pas le faire fonctionner correctement. Toute aide est très appréciée, et si vous avez besoin d'autres informations, veuillez demander!
Capture d'écran MISE À JOUR avec solution - contraintes buttonZ:
EDIT @ Jamie Forrest La solution s'avère donc être la mauvaise contrainte de fin sur le dernier bouton. Au lieu de 6441, la valeur que j'avais définie était négative, -6441. Le problème est que lors de la définition de la valeur dans le storyboard, il existe deux options dans la barre d'outils Épingler:
La valeur actuelle du canevas est négative (conduisant à aucun défilement) et l'option ci-dessous est positive (activation du défilement). Cela signifie que je ne suis pas stupide mais au moins à moitié aveugle je suppose. Cependant, pour ma défense, n'est-il pas quelque peu dérangeant que XCode n'affiche pas d'erreur pour le paramètre «incorrect»?
MODIFIE DE NOUVEAU Maintenant c'est drôle ... changer la valeur de fin de -6441 (pas de défilement) à 6441 défilement activé. Mais mon vieil ami le "too much contentsize" était de retour, conduisant à une taille de contenu deux fois plus grande que ce qu'elle devrait être! La solution pour obtenir le défilement de contenu correct était de définir la contrainte de fin sur ZERO! Ce n'est pas évident lorsque vous travaillez dans Storyboard, mais en regardant le code de @Infinity James, c'est ce qu'il devrait être.
la source
contentSize
d'uneUIScrollView
mise en page automatique uniquement. Et c'est lecontentSize
qui définit combien vous pouvez faire défiler. Vous devrez donc éventuellement définir cela manuellement quelque part. Pour le reste, vous pouvez utiliser des contraintes de mise en page pour configurer les cadres de vue les uns par rapport aux autres.Réponses:
Il est difficile de voir les valeurs exactes et la configuration de vos contraintes lorsque vous les avez collées ici, donc je ne suis pas sûr de regarder vos captures d'écran où vous vous êtes trompé.
Au lieu d'expliquer ce qui ne va pas dans votre configuration, j'ai créé un exemple de projet de base avec une hiérarchie de vues et une configuration de contraintes très similaires à celles que vous décrivez. Le défilement horizontal fonctionne comme prévu dans l'exemple de projet, qui utilise l'approche «Pure AutoLayout» décrite par Apple dans la note technique .
J'ai également eu beaucoup de mal à faire fonctionner la mise en page automatique
UIScrollView
. La clé pour le faire fonctionner est de s'assurer que tous les éléments de la vue de défilement, pris ensemble, ont des contraintes qui finissent par se lier à tous les côtés de la vue de défilement et qui contribuent à ce que le système de mise en page automatique puisse déterminer une taille de contenu pour le vue de défilement qui sera plus grande que son cadre. Il semble que vous essayiez de le faire dans votre code, mais peut-être que vous aviez des contraintes superflues qui rendaient le contentSize trop petit.Notez également que, comme d'autres l'ont mentionné, avec AutoLayout et UIScrollview, vous ne définissez plus explicitement contentSize. Le système AutoLayout calcule le contentSize en fonction de vos contraintes.
J'ai également trouvé ce chapitre d'ebook très utile pour me faire comprendre comment tout cela fonctionne. J'espère que tout cela aide.
la source
Bienvenue LOL au club de stupidité. Je suis l'un des fondateurs. :RÉ
Pour le défilement VERTICAL : le seul moyen de le faire fonctionner (iOS 8, Xcode 6 et mise en page automatique pure) était d'ajouter les contraintes suivantes à ma vue de défilement (toutes liées à la supervision):
Ma structure:
Voici le résultat final:
Voici la configuration:
Plein écran
J'espère que cela éviterait à quelqu'un d'aller dormir à 5 heures du matin. :RÉ
la source
Exemple autonome simple
À en juger par le nombre élevé de votes sur la question et le faible nombre de votes sur les réponses, les gens ne trouvent pas ici de solution compréhensible et rapide. Permettez-moi d’en ajouter un. Ce projet est un exemple autonome réalisé entièrement dans Interface Builder. Vous devriez pouvoir y travailler en 10 minutes ou moins. Ensuite, vous pouvez appliquer les concepts que vous avez appris à votre propre projet.
La question d'origine porte sur les boutons de défilement. Ici, j'utilise juste des
UIView
s mais ils peuvent représenter la vue que vous aimez. J'ai également choisi le défilement horizontal car les captures d'écran du storyboard sont plus compactes pour ce format. Les principes sont les mêmes pour le défilement vertical, cependant.Concepts clés
UIScrollView
ne doit utiliser qu'une seule sous-vue. Il s'agit d'un 'UIView' qui sert de vue de contenu pour contenir tout ce que vous souhaitez faire défiler.Commencer un nouveau projet
Il peut s'agir d'une simple application d'affichage.
Storyboard
Dans cet exemple, nous allons créer une vue de défilement horizontal. Sélectionnez le contrôleur de vue, puis choisissez Forme libre dans l'inspecteur de taille. Faites la largeur
1,000
et la hauteur300
. Cela nous donne juste de la place sur le storyboard pour ajouter du contenu qui défilera.Ajouter une vue de défilement
Ajoutez a
UIScrollView
et épinglez les quatre côtés à la vue racine du contrôleur de vue.Ajouter une vue de contenu
Ajoutez un
UIView
comme sous-vue à la vue de défilement. C'est la clé. N'essayez pas d'ajouter beaucoup de sous-vues à la vue de défilement. Ajoutez simplement un seulUIView
. Ce sera votre vue de contenu pour les autres vues que vous souhaitez faire défiler. Épinglez la vue de contenu à la vue de défilement sur les quatre côtés.Hauteur égale
Maintenant, dans la structure du document, Commandcliquez à la fois sur la vue de contenu et sur la vue parente de la vue de défilement afin de les sélectionner toutes les deux. Ensuite, définissez les hauteurs pour qu'elles soient égales ( Controlfaites glisser de la vue de contenu vers la vue de défilement). C'est également la clé. Comme nous faisons défiler horizontalement, la vue du contenu de la vue de défilement ne saura pas à quelle hauteur elle devrait être à moins que nous ne la définissions de cette manière.
Remarque:
Ajouter du contenu
Ajoutez trois
UIView
s et donnez-leur toutes les contraintes. J'ai utilisé des marges de 8 points pour tout.Contraintes:
La définition des contraintes de largeur est également essentielle pour que la vue de défilement sache la largeur de sa vue de contenu.
Fini
C'est tout. Vous pouvez exécuter votre projet maintenant. Il devrait se comporter comme l'image défilante en haut de cette réponse.
Pour le défilement vertical, permutez simplement toutes les directions de largeur et de hauteur dans cet exemple (testé et fonctionnel).
Une étude plus approfondie
la source
Le contentSize est implicitement défini en appliquant les contraintes à l'intérieur de UIScrollView.
Par exemple, si vous avez un UIScrollView à l'intérieur d'un UIView, il ressemblera à ceci (comme je suis sûr que vous le savez):
Cela définira le scrollView pour remplir la taille du containerView (donc le containerView devra être d'une certaine taille).
Vous pouvez ensuite ajuster le contentSize de UIScrollView en le définissant implicitement pour qu'il soit suffisamment grand pour contenir les boutons comme ceci:
la source
Il y a tellement de questions sur l'utilisation de la mise en page automatique avec UIScrollView, le point clé que nous ignorons est que les vues internes de UIScrollView font des contraintes sur la vue de contenu mais pas sur UIScrollView lui-même. Reportez-vous à la note technique TN2154 , vous pouvez trouver:
La figure suivante montre que:
Vous pouvez trouver que l'espace de fin est de 500 points, si la contrainte est appliquée à UIScrollView, la vue sera mal placée et devrait être mise à jour son cadre. Cependant, aucun avertissement et aucune erreur. Parce que toutes les contraintes sont contre la vue du contenu.
UIScrollView calculera la taille de la vue de contenu en fonction des contraintes des vues intérieures. (Pour l'exemple, la taille du contenu: largeur = 100 (espace de début) + 200 (largeur de la vue) + 500 (espace de fin), hauteur = 131 (espacement du haut) + 200 (hauteur) + 269 (espacement du bas))
Comment ajouter des contraintes pour les vues dans UIScrollView:
Et tout est fait.
Un moyen simple de gérer la mise en page automatique avec scrollview consiste à ajouter une vue de conteneur contenant toutes les sous-vues dans la vue de défilement.
Conclusion: le point clé pour comprendre AutoLayout avec UIScrollView est que les vues internes créent des contraintes contre la vue de contenu mais pas UIScrollView lui-même.
code d'exemple joint
la source
La solution suivante a fonctionné pour moi pour scrollView avec autolayout et sans contentSize :
Et tu as fini. Maintenant, vous pouvez ajouter n'importe quel nombre de contrôles sur cette vue et appliquer les contraintes pertinentes les unes aux autres (qui ne semblent pas fonctionner sans cette vue). Si vous ne souhaitez pas utiliser cette vue, vous devrez appliquer des contraintes pour chaque contrôle lié à scrollView (non liés les uns aux autres).
Le conseil écrasant ..............
Critique . Disons que pour plus de clarté, l'UIScrollView a une largeur de 1000 et une hauteur de 100. (En fait, normalement, ces valeurs seraient dynamiques, bien sûr, en fonction de la largeur de l'appareil, etc. Mais pour l'instant, disons simplement 1000 de large et 100 de haut.) Disons que vous faites un défilement horizontal. Mettez donc un UIView dans UIScrollView. (C'est la "vue de contenu".) Définissez les quatre contraintes de la vue de contenu haut, bas, début, fin, sur la vue de défilement. Faites-les tous à zéro, même si cela semble faux. Définissez la hauteur du contenu UIView sur 100 et oubliez cela. Maintenant: vous voulez faire défiler horizontalement, alors définissez la largeur de la vue du contenu sur 1225.
Notez que la largeur de la vue de contenu est maintenant 225 plus grande que la largeur de la vue de défilement parent. C'est OK: en fait, vous DEVEZ le faire. Notez que
... vous ne définissez PAS la largeur de fin sur moins de 225 ...
vous penseriez que vous devez "faire correspondre" les largeurs comme vous le feriez normalement . Mais si vous faites cela, cela ne fonctionnera pas du tout.
Vous devez définir les nombres de début et de fin sur ZERO , jamais négatifs (même si la largeur est "plus grande")
Fait intéressant, vous pouvez en fait définir les nombres de début / de fin sur n'importe quelle valeur positive (essayez de dire «50») et cela vous donne une sorte de marge du rebond. (Cela a souvent l'air génial: essayez-le.) Toute valeur négative à l'une ou l'autre extrémité "cassera silencieusement".
Notez que, de manière exaspérante, souvent Xcode (à partir de 7.3.1 de toute façon),
va "utilement" définir ces valeurs pour vous sur des nombres négatifs!
car il essaie de les compter automatiquement pour vous. Si c'est le cas, il se cassera silencieusement. Définissez les quatre valeurs sur zéro dans la première instance. Et définissez la largeur de la vue du contenu beaucoup plus large que le "1000" dans l'exemple.
Modifié: j'ai fini par utiliser UITableView au lieu de UIScrollView pour la plupart de mes besoins. Comme tableView me semble beaucoup plus flexible et dynamique.
la source
Je suppose que vous rencontrez des problèmes avec le
contentSize
. Consultez ce billet de blog sur la façon de gérer lecontentSize
lors de l'utilisation d'une approche de mise en page automatique «pure». L'essentiel est que vos contraintes définissent implicitement la taille du contenu. Vous ne le définissez JAMAIS explicitement lors de l'utilisation de la mise en page automatique. J'ai joint un exemple de projet à la fin de l'article de blog pour montrer comment cela fonctionnela source
Il y a un élément dans les notes techniques que vous avez peut-être examiné. Vous pouvez définir implicitement la taille du contenu d'une vue de défilement à l'aide de contraintes fixées aux bords de la vue de défilement.
Voici un exemple simple. Créez un storyboard avec une vue, qui a une vue de défilement. Définissez ces contraintes de vues de défilement pour qu'elles correspondent à la taille de la vue dans laquelle vous les placez.
À l'intérieur de cette vue de défilement, ajoutez une vue unique. Définissez explicitement la taille de cette vue à l'aide de contraintes (et assurez-vous que cette taille est plus grande que la vue de défilement).
Ajoutez maintenant quatre contraintes supplémentaires à cette vue intérieure en verrouillant les quatre bords de la vue intérieure à sa vue de défilement parente. Ces quatre contraintes entraîneront l'expansion de la taille du contenu pour s'adapter à la vue intérieure.
Si vous souhaitez ajouter plusieurs vues à une vue de défilement, par exemple disposées horizontalement, vous verrouillez le côté gauche de la première sous-vue à gauche de la vue de défilement, verrouillez les sous-vues les unes aux autres horizontalement et à droite. côté de la dernière vue secondaire à droite de la vue de défilement. Ces contraintes forceraient la taille du contenu de la vue de défilement à se développer pour s'adapter à toutes les sous-vues et à leurs contraintes.
la source
Si votre question est "Comment puis-je mettre un tas de UITextFields dans un UIScrollView à défilement vertical de telle sorte qu'ils se déplacent hors du chemin du clavier lorsqu'ils ont le focus", la meilleure réponse est:
Ne fais pas ça.
Utilisez plutôt un UITableViewController avec des cellules statiques.
Vous obtenez ce comportement de défilement hors du chemin gratuitement, ET tous les inserts de contenu fonctionnent simplement si votre contrôleur de vue est affiché dans un UINavigationController.
la source
Vous devez organiser votre mise en page comme ceci
ViewControllerView
contientScrollView
,ScrollView
contientContainerView
,ContainerView
contient 2Labels
Puis suivez 3 étapes pour faire
ScrollView
défiler votre canScrollView
broche (haut / droite / bas / gauche) surViewControllerView
ContainerView
broche (haut / droite / bas / gauche) surScrollView
Horizontally in Container
( ne pas définirVertically in Container
)Label1
broche ( haut / droite / gauche) àContainerView
Label1
broche (droite / gauche / bas ) versContainerView
et haut versLabel1
J'espère que cette aide
la source
L'approche de mise en page automatique pure fonctionne à merveille, mais la configuration est assez pénible si vous migrez à partir d'une mise en page non automatique. Je l'ai fait plusieurs fois maintenant et j'ai quelques conseils généraux:
la source
Après un certain temps à traiter ce problème, j'ai finalement trouvé une solution. Je travaille avec des storyboards de taille de classe universelle (600x600). J'ai créé un UIView (contentView) de la taille du scrollView et créé des contraintes pour Top, Bottom, Leading et Trailing pour le scrollView. Ensuite, j'ai coupé manuellement la taille du contentView à 600x600. Le storyboard a cessé d'essayer de tout redimensionner et j'ai pu travailler mais la vue était horrible sur le vrai appareil ou le simulateur. J'ai réalisé 2 prises de contrainte de cette taille coupée.
Puis dans viewDidLoad
Fonctionne très bien.
la source
J'ai passé des jours à essayer de trouver une solution sur la façon d'utiliser la mise en page automatique pour afficher une vue de défilement intégrée, pour centrer la vue de défilement dans l'écran visible, qui fonctionne sur tous les appareils / dimensions d'écran ainsi qu'avec la rotation de l'écran.
J'ai passé des jours à essayer de le faire avec Autolayout uniquement, et je me suis rapproché mais jamais assez. Donc, à la fin, j'ai dû ajouter 3 lignes de code par écran également, dans viewDidLoad.
Voir la solution ci-dessous:
Allez maintenant dans le fichier .m et ajoutez ces lignes de code dans viewDidLoad (jouez avec la quantité de remplissage pour obtenir le bon centrage vert)
{self.constraintVertVtoSV.constant = 150,0; }
cela devrait maintenant fonctionner sur tous les appareils et être correctement centré et toujours défiler correctement.
la source
Si, comme moi, vous utilisez simplement du contenu statique sans contraintes à l'intérieur de la sous-vue, comme vous pouvez le faire comme ceci:
la source
Problème similaire que j'ai aujourd'hui avec iOS 8.4, Xcode 6.4
Là, une vue contenant une vue de défilement, contenant un contentView (UIView) contenant des sous-vues.
Tout est mise en page automatique partout. Les bords de la vue de défilement sont épinglés aux bords de la vue parent avec des contraintes. Les bords de la vue de contenu sont épinglés aux bords de la vue de défilement avec des contraintes.
À l'origine, la vue de contenu refusait de prendre la taille totale de la vue de défilement. J'ai dû ajouter une contrainte supplémentaire sur la vue du contenu pour que sa largeur corresponde à la vue de défilement parent. Ou je pourrais définir une contrainte contentView.centerX == scrollView.centerX. L'un ou l'autre de ceux-ci en plus d'épingler les bords a soudainement rendu le contenu affiché correctement.
Épingler les bords de la vue de contenu à la vue de défilement à l'aide des contraintes visuelles du formulaire,
J'utilise une routine pour parcourir le tableau et les ajouter au scrollView.
la source
J'ai fait face à un problème similaire. J'ai défini chaque contrainte et je me suis toujours demandé pourquoi il redimensionnait encore certaines sous-vues. Ma solution a été de régler clipsToBounds sur YES.
la source
En rapide, vous pouvez utiliser cette solution de travail.
Contraintes
ScrollView
: Avant, Arrière, Haut, Bas = Vue d'ensembleContentView
: Début, Fin, Haut, Bas = ScrollView. Hauteur fixe / relative au contenu.Vous pouvez définir la contrainte de largeur (contentView) pour égaliser les vues de défilement superview, mais sélectionnez supprimer supprimer au moment de la génération, car vous ajouterez cette contrainte par programme. C'est juste pour que l'IB ne se plaint pas d'avertissements.
Et dans View Controller,
viewDidLayoutSubviews
j'appelle simplement cette méthode:la source
Je sais que c'est une solution profane et non ce qu'Apple suggère dans le docu, mais cela a fonctionné pour moi deux fois, avec un contenu différent et peut être configuré très rapidement: dans le contrôleur de vue storyboard, insérez UIView. Dans UIView, insérez une vue de tableau, dynamique, 0 cellule de prototype, style simple ou groupé. Dans la vue de tableau, insérez une vue de défilement, dans la vue de défilement, insérez du contenu. C'est tout, pas de paramètres dans le contrôleur de vue personnalisé.
la source