Ambiguïté de la taille du contenu défilable UIScrollView

512

Chers développeurs, j'ai des problèmes avec AutoLayout dans Interface Builder (Xcode 5 / iOS 7). C'est très basique et important, donc je pense que tout le monde devrait savoir comment cela fonctionne correctement. S'il s'agit d'un bogue dans Xcode, il est critique!

Donc, chaque fois que j'ai une hiérarchie de vues comme celle-ci, je rencontre des problèmes:

>UIViewController
>> UIView
>>>UIScrollView
>>>>UILabel (or any other comparable UIKit Element)

Le UIScrollView a des contraintes solides, par exemple, 50 px de chaque côté (pas de problème). Ensuite, j'ajoute une contrainte Top Space à l'UILabel (pas de problème) (et je peux même épingler la hauteur / largeur de l'étiquette, ne change rien, mais ne devrait pas être nécessaire en raison de la taille intrinsèque de l'étiquette)

Le problème commence lorsque j'ajoute une contrainte de fin à l'UILabel:

Par exemple, Trailing Space to: Superview Equals: 25

Maintenant, deux avertissements se produisent - et je ne comprends pas pourquoi:

A) Ambiguïté de la taille du contenu défilable (la vue de défilement présente une hauteur / largeur de contenu défilant ambigu)

B) Vues mal placées (étiquette attendue: x = -67 réelle: x = 207

J'ai fait cet exemple minimal dans un nouveau projet que vous pouvez télécharger et j'ai joint une capture d'écran. Comme vous pouvez le voir, Interface Builder s'attend à ce que l'étiquette se trouve en dehors de la limite de UIScrollView (le rectangle en pointillés orange). La mise à jour du cadre du libellé avec l'outil Résoudre les problèmes le déplace là.

Remarque: si vous remplacez UIScrollView par UIView, le comportement est conforme aux attentes (le cadre de l'étiquette est correct et conforme à la contrainte). Il semble donc qu'il y ait un problème avec UIScrollView ou que je manque quelque chose d'important.

Lorsque j'exécute l'application sans mettre à jour le cadre du Label comme suggéré par IB, il est très bien positionné, exactement là où il est censé être et UIScrollView peut défiler. Si je mets à jour le cadre, l'étiquette est hors de vue et l'UIScrollView ne défile pas.

Aidez-moi Obi-Wan Kenobi! Pourquoi cette disposition ambiguë? Pourquoi cette vue déplacée?

Vous pouvez télécharger l'exemple de projet ici et essayer de comprendre ce qui se passe: https://github.com/Wirsing84/AutoLayoutProblem

Illustration du problème dans Interface Builder

Wirsing
la source
8
Essayez de placer l'UILabel dans une vue de contenu, puis définissez le bord de fuite de l'étiquette sur la vue de contenu (UIView standard). Cette vidéo peut vous aider grandement: youtube.com/watch?v=PgeNPRBrB18&feature=youtu.be
erdekhayser
1
Super vidéo mais elle n'a pas corrigé les avertissements pour moi. :(
M. Rogers
Merci beaucoup pour la vidéo - il y a eu (assez surprenant) beaucoup de choses que j'ai apprises! Cependant, lorsque je combine les connaissances de la vidéo avec stackoverflow.com/questions/18953617/… je peux corriger les avertissements. La question qui demeure est la suivante: comment rendre la taille contentView du scrollView aussi grande que nécessaire?
Wirsing
Jetez un œil à cette vidéo. Il montre comment utiliser UIScrollLayout et autolayout avec XCode 5 / iOS 7.
jaxvy
Ma suggestion est de ne pas utiliser UIScrollViewdirectement. Au lieu d'utiliser UICollectionViewou UITableViewautant que possible, la plupart du temps, tout est possible avec ces éléments et cela donne également la simplicité, la lisibilité et la réutilisation !!!
SPatel

Réponses:

1093

Je viens donc de trier de cette façon:

  1. À l'intérieur de l' UIScrollView ajout d' un UIView(on peut appeler cela contentView);

  2. Dans ce cas contentView, définissez les marges supérieure, inférieure, gauche et droite à 0 (bien sûr à partir de scrollViewlaquelle est la superView); Définissez également aligner le centre horizontalement et verticalement ;

Terminé .

Maintenant, vous pouvez ajouter toutes vos vues en cela contentView, et contentSizele scrollViewsera automatiquement redimensionné en fonction du contentView.

Mise à jour:

Certains cas particuliers sont couverts par cette vidéo publiée par @Sergio dans les commentaires ci-dessous.

Matteo Gobbi
la source
33
Presque parfait, sauf que la vue de défilement ne peut plus deviner la longueur de votre contenu et redimensionner en conséquence, c'est contentSize pour s'adapter aux objets à l'intérieur. J'ai une vue de table à l'intérieur de contentView dont la hauteur change (via une contrainte) et la vue de défilement ne me permet pas de faire défiler.
CyberMew
28
Peut-être que cette vidéo peut aider à surmonter tous les problèmes restants.
Sergio
46
cela ne le fait pas défiler.
dorian
2
@MatteoGobbi C'était tout! Ça a fait l'affaire! A eu du mal avec ce genre de problèmes de folie scrollView autoLayout pendant 2 jours .... Merci mec !!!
polo987
56
Pour toute personne confrontée à un problème avec ScrollView ne pouvant pas défiler, définir le bas de contentView et aligner le centre verticalement avec des contraintes de faible priorité a fait l'affaire pour moi!
jimmy0251
98

Cette erreur m'a pris un certain temps à rechercher, au début, j'ai essayé d'épingler la taille du ScrollView mais le message d'erreur indique clairement "taille du contenu". Je me suis assuré que tout ce que j'avais épinglé en haut du ScrollView était également épinglé en bas. De cette façon, ScrollView peut calculer la hauteur de son contenu en trouvant la hauteur de tous les objets et contraintes. Cela a résolu la hauteur du contenu ambigu, la largeur est assez similaire ... Au départ, la plupart des choses étaient centrées sur X dans le ScrollView, mais je devais également épingler les objets sur le côté du ScrollView. Je n'aime pas cela parce que l'iPhone6 ​​pourrait avoir un écran plus large, mais cela supprimera l'erreur «largeur de contenu ambiguë».

self.name
la source
31
Merci pour votre réponse! Si je vous comprends bien, vous parvenez à supprimer l'erreur en épinglant chaque sous-vue dans ScrollView en haut et en bas. Toutefois, ce n'est pas nécessaire. Il vous suffit de vous assurer qu'il existe un moyen de créer une ligne continue de contraintes du haut vers le bas de la vue de défilement. [-XXX] J'espère que c'était compréhensible;>
Wirsing
1
Comment résoudre le problème si la vue a une hauteur variable? Comment puis-je configurer les contraintes pour que la vue déroulante puisse calculer les tailles?
hashier
2
«Vous devez simplement vous assurer qu'il existe un moyen de créer une ligne continue de contraintes du haut vers le bas de la vue de défilement» <- merci pour cette phrase
Adam Waite
3
Ce qui m'a aidé était de m'assurer que la vue de défilement était épinglée sur la vue d'ensemble et non sur les guides de mise en page supérieurs ou inférieurs. J'ai supprimé la contrainte du guide de mise en page inférieur et parcouru le menu au lieu du générateur d'interface. Éditeur -> Épingler -> Espace inférieur vers Superview.
Alberto Lopez
2
Si vous souhaitez que la largeur de la vue de défilement suive la largeur de l'écran de votre téléphone ou de tout autre élément de votre interface utilisateur (comme la vue UIV contenant), vous devez définir une "largeur égale" en utilisant un autre élément en dehors de la vue de défilement pour la mesure.
Departamento B du
89

Xcode 11+

La manière la plus simple d'utiliser autolayout:

  1. Ajoutez-le UIScrollViewet épinglez-le 0,0,0,0à la vue d'ensemble (ou à la taille souhaitée)
  2. Ajoutez UIViewScrollView, épinglez-le 0,0,0,0sur les 4 côtés et centrez-le horizontallyet vertically.
  3. Dans l'inspecteur de taille, changez bottomet align center Ydonnez la priorité à 250. (pour le changement de défilement horizontal trailinget align center X)
  4. Ajoutez toutes les vues dont vous avez besoin dans cette vue. N'oubliez pas de définir la contrainte inférieure sur la vue la plus basse.
  5. Sélectionnez le UIScrollView, sélectionnez l'inspecteur de taille et désélectionnez Content Layout Guides.
Đorđe Nilović
la source
1
Je n'ai pas pu définir la hauteur du contenu de scrollview mais cela fonctionne. :)
Blind Ninja
2
Astuce: par moi, cela ne fonctionnait que si je supprimais le centre horizontalement et verticalement et le remplaçais par une largeur égale (scrollView + vue à l'intérieur de scrollView) ET en ajoutant la hauteur en fonction du contenu, ce qui signifie que le dernier élément de la vue a besoin d'une contrainte inférieure. Regardez ici pour plus d'informations: stackoverflow.com/a/54577278/5056173
Sean Stayns
1
Sean, j'utilise cela littéralement tous les jours et je n'ai jamais eu de problème avec cette approche en ce qui concerne le défilement vertical et horizontal. Vous avez peut-être oublié de mettre une contrainte inférieure sur l'élément le plus bas / dernier. Sans cela, cela ne fonctionnera pas.
Đorđe Nilović
7
Point numéro 4 - la deuxième phrase est la grande.
Nitish
2
cette réponse a parfaitement fonctionné pour moi
satvinder singh
63

C'est la réponse à ma question auto-répondue UIScrollView + Vue Centrée + Taille de Contenu Défilable Ambigous + plusieurs tailles d'iPhone .

Mais cela couvre également votre cas!

Voici donc l'état initial du cas le plus simple:

  1. scrollView avec 0 contraintes sur toutes les arêtes
  2. Bouton horizontal et vertical centré avec des contraintes de largeur et de hauteur fixes
  3. Et, bien sûr - des avertissements ennuyeux Has ambiguous scrollable content width et Has ambiguous scrollable content height.

1

Tout ce que nous devons faire, c'est:

  • Ajoutez 2 contraintes supplémentaires, par exemple "0" pour l' espace de fin et / ou inférieur pour notre vue (regardez l'exemple sur la capture d'écran ci-dessous).

Important: vous devez ajouter des contraintes de fin et / ou de fond . Pas "leader et top" - ça ne marche pas!

2

Vous pouvez le vérifier dans mon exemple de projet , qui montre comment résoudre ce problème.

PS

Selon la logique - cette action devrait provoquer des "contraintes conflictuelles". Mais non!

Je ne sais pas pourquoi cela fonctionne et comment Xcode détecte quelle contrainte est la plus prioritaire (parce que je ne suis pas défini comme prioritaire pour ces contraintes explicitement). Je serai reconnaissant si quelqu'un explique pourquoi cela fonctionne dans les commentaires ci-dessous.

skywinder
la source
Bon conseil! J'ai fini par créer une contrainte sur le bord inférieur et définir la priorité sur moyen ou bas
Dean
Hou la la! Cela n'a vraiment aucun sens, mais ça marche! Je vous remercie! Le dernier élément que j'ai à mon avis, j'ai défini une contrainte inférieure de 0 et BANG. Enfin travaillé.
Jakob Hviid,
60

Xcode 11+, Swift 5

Si vous vous demandez pourquoi toutes les réponses ne fonctionnent plus, assurez-vous que vous avez épinglé la vue de contenu (celle que vous avez placée dans la vue de défilement) au Guide de disposition du contenu de la vue de défilement et NON au Guide de disposition des cadres.

Les bords de la vue du contenu (début, fin, haut, bas) ne doivent pas être épinglés comme les premiers sur l'image - vers le guide de disposition du cadre

Pas comme ça

mais comme ça - au Content Layout Guide.

Sélectionnez Guide de mise en page du contenu dans la liste déroulante

entrez la description de l'image ici

Et puis la plupart des réponses fonctionneront pour vous.

L'approche la plus simple se déroule maintenant comme ceci:

  1. Mettre la vue de défilement dans la vue racine
  2. Épinglez tous les côtés de la vue de défilement dans la vue d'ensemble
  3. Prenez une autre UIView (l'appellera vue de contenu) et placez-la dans la vue de défilement
  4. Épinglez tous les côtés de la vue du contenu pour faire défiler le Guide de présentation du contenu de la vue
  5. Épinglez la largeur de la vue de contenu pour qu'elle soit égale au guide de disposition des cadres de la vue de défilement
  6. Fixez la hauteur de la vue du contenu comme vous le souhaitez (j'ai utilisé une contrainte de hauteur constante dans l'exemple ci-dessous)

Dans l'ensemble, votre structure dans la mise en œuvre la plus simple ressemblera à ceci

entrez la description de l'image ici

Vouloir savoir
la source
@WantToKnow Pas besoin de prendre la contrainte de hauteur, il suffit de changer sa priorité sur low (250)
Reckoner
Xcode 11+, Swift 5. Selon la réponse de @WantToKnow, j'ai résolu mon problème, j'ai préparé [vidéo] [1] et [code] [2] [1]: youtube.com/watch?v=qMrH5_Yj5hM [2]: github.com/AhmAbdallah/CustomCollectionView
Ahmed Abdallah
1
Ceci est une excellente réponse, merci.
Constantine
1
C'est la bonne réponse. Merci.
Vincent Joy
Cela n'a fonctionné pour moi que lorsque j'ai ajouté la contrainte inférieure au dernier élément de la vue de contenu
D.Zotov
49

Vous devez créer un UIViewsous-vue du UIScrollViewcomme décrit ci-dessous:

  • UIViewController
  • UIView 'Vue principale'
    • UIScrollView
      • UIView «Vue conteneur»
        • [Votre contenu]

La deuxième étape consiste à faire les UIScrollViewcontraintes. Je l'ai fait avec les contraintes supérieure, inférieure, avant et arrière de sa superView.

Ensuite, j'ai ajouté les contraintes pour le conteneur de UIScrollViewet c'est ici que le problème commence. Lorsque vous mettez les mêmes contraintes (haut, bas, début et fin), le Storyboard donne un message d'avertissement:

"A une largeur de contenu défilant ambigu" et "A une hauteur de contenu défilant ambigu"

Continuez avec les mêmes contraintes ci-dessus, et ajoutez simplement les contraintes Equal Heightet Equal Widthà votre vue de conteneur par rapport à la vue principale et non à votre UIScrollView. En d'autres termes, les contraintes de la vue conteneur sont liées à la vue d'ensemble du UIScrollView.

Après cela, vous n'aurez plus d'avertissement dans votre Storyboard et vous pourrez continuer à ajouter les contraintes pour vos sous-vues.

Thiago Monteiro
la source
2
D'accord - Je pense que l'ajout d'une vue de conteneur est la meilleure solution, la plus maintenable.
Andrew Ebling
1
Cette solution fonctionne lorsque vous n'avez pas de barre de navigation à gérer.
Leena
27

J'ai eu le même problème. Décochez cette case. Puisque vous définissez la taille du contenu dans le code. entrez la description de l'image ici

Yodagama
la source
24

J'ai finalement compris cela, j'espère que c'est plus facile à comprendre.

Vous pouvez souvent contourner cet avertissement en ajoutant une UIView de base à la vue de défilement en tant que "vue de contenu", comme ils l'ont mentionné et en lui donnant la même taille que votre vue de défilement et, sur cette vue de contenu, définissez ces 6 paramètres.

entrez la description de l'image ici

Comme vous pouvez le voir, vous avez besoin de 6 paramètres au total! Ce qui .. dans des circonstances normales, vous dupliquez 2 contraintes mais c'est le moyen d'éviter cette erreur de storyboard.

William T.
la source
1
Ce qui précède a presque fonctionné pour moi, car je suis préoccupé par 3 largeurs d'écran différentes (4/5, 6, 6+). J'ai défini la vue du contenu et la vue de défilement pour avoir des largeurs égales. Vous avez raison, c'est un doublon car j'ai déjà dit à la vue de contenu d'avoir 0 espace de début et de fin.
Stuart P.
8
Vous pouvez définir des contraintes de largeur et de hauteur égales de la vue de contenu à la vue de défilement, au lieu de valeurs constantes. Cela fonctionnera sur toutes les résolutions.
Kumar C du
Je dois implémenter le même, alors pouvez-vous m'aider à définir une hauteur et une largeur égales pour la vue de contenu et la vue de défilement?
Urmi
Cela pourrait valoir la peine de vérifier si vous devez encore le faire. J'ai mis en place une imageView dans une scrollview récemment et j'ai pu m'en sortir en ne définissant que les 4 contraintes affichées en haut pour faire disparaître l'erreur dans Xcode 8.3
William T.
1
@Honey, cela a été publié il y a plus de 3 ans. Depuis, ils ont définitivement amélioré les storyboards. J'ai aussi remarqué que vous pouvez vous en sortir sans la vue du contenu maintenant. Je vais ajuster ma réponse.
William T.
16

Je sais que je suis peut-être en retard, mais la prochaine solution résout ce genre de problèmes sans code supplémentaire , en utilisant simplement des storyboards:

Pour votre affichage de contenu, vous devez définir des contraintes pour les espaces de début / de fin / haut / bas pour faire défiler la vue et cela ne changera pas le cadre d'affichage de contenu , comme ceci:entrez la description de l'image ici

Bien sûr, vous devez créer des contraintes supplémentaires pour la vue du contenu afin que la vue de défilement puisse connaître la taille du contenu. Par exemple, définissez une hauteur et un centre fixes x.

J'espère que cela t'aides.

Borzh
la source
7

Pour moi, l'ajout d'un contentViewn'a pas vraiment fonctionné comme suggéré. De plus, cela crée un surcoût en raison de la vue ajoutée (bien que je ne considère pas cela comme un gros problème). Ce qui a fonctionné le mieux pour moi, c'était juste de désactiver la vérification d' ambiguïté pour moi scrollView. Tout se passe bien, donc je pense que ça va dans des cas simples comme le mien. Mais gardez à l'esprit que si d'autres contraintes pour votre scrollViewpause, l'Interface-Builder ne vous en avertira plus.

entrez la description de l'image ici

Nick Podratz
la source
5
Cela supprimera simplement l'avertissement et ne fera rien pour résoudre le problème.
Predrag Manojlovic
Vous. sont. mon. héros. Je ne savais pas que cela existait et je suis ravi de le trouver! J'ai essayé "Vérifier la position uniquement", ce à quoi vous vous attendez, je ne sais pas, vérifiez la position uniquement, mais non, cela permet également ce problème de "taille du contenu". Je dois y aller avec "Never Verify". Merci!
Dustin
Je pense que c'est la bonne réponse si vous créez la vue enfant par programme. Merci!
Florian Kusche
6

Découvrez ce tutoriel très rapide et pertinent sur la façon de faire fonctionner la vue de défilement et de la faire défiler entièrement avec la mise en page automatique. Maintenant, la seule chose qui me laisse encore perplexe est la raison pour laquelle la taille du contenu de la vue de défilement est toujours plus grande que nécessaire.

http://samwize.com/2014/03/14/how-to-use-uiscrollview-with-autolayout/

Mike Simz
la source
3

Voir ci-dessous: affichage du contenu en scrollview vertical et horizontal centralisé. vous avez une erreur d'ambiguïté, assurez-vous toujours que deux éléments ajoutés dans la vue de défilement de votre vue de contenu sont 1) .bouton d'espace vers le conteneur.2) espace de fin à la contrainte qui est mis en évidence dans la capture d'écran,

ces contraintes signifient que dans le défilement, vous pouvez défiler après la hauteur ou la largeur de votre vue de contenu.

entrez la description de l'image ici

cela peut vous aider.

Ravi Kumar
la source
3

J'ai résolu ce type de problème pour ma vue en utilisant "Résoudre les problèmes de disposition automatique"> "Ajouter des contraintes manquantes" pour la vue sélectionnée entrez la description de l'image ici

Les deux contraintes suivantes résolvent mon problème:

trailing = Stack View.trailing - 10
bottom = Stack View.bottom + 76

dans lequel: en bas, en bas sont les derniers, en bas de UIScrollView

Linh Dao
la source
Cela a fonctionné pour moi en ajoutant une contrainte "to bottom". Maintenant que j'y pense, c'est parfaitement logique.
SilverWolf
3

L' utilisation contentView ( UView) comme à l' intérieur du conteneur UIScrollView, bâton aux bords ( top, bottom, trailing, leading) de superview ( UIScrollView) et contentViewdevrait avoir equalwidthet equalheightà superview. Ce sont des contraintes. Et appel de méthode:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    self.scrollView.contentSize = self.contentView.frame.size;
}

Problèmes résolus pour moi.

Spiridon Kopicl
la source
3

Approche Swift 4+:

1) Définissez les marges supérieure, inférieure, gauche et droite d'UIScrollView sur 0

2) À l'intérieur de UIScrollView, ajoutez une UIView et définissez les marges supérieure, inférieure, avant et arrière à 0 (égale aux marges UIScrollView).

3) La partie la plus importante est de définir la largeur et la hauteur, où la contrainte de hauteur doit avoir une faible priorité .

private func setupConstraints() {

    // Constraints for scrollView
    scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

    // Constraints for containerView
    containerView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
    containerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
    containerView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
    containerView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
    containerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true

    let heightConstraint = containerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor)
    heightConstraint.priority = UILayoutPriority(rawValue: 250)
    heightConstraint.isActive = true
}
Gentian Sadiku
la source
2

La réponse de @Matteo Gobbi est parfaite, mais dans mon cas, la vue de défilement ne peut pas défiler, je supprime " aligner le centre Y " et ajoute " hauteur> = 1 ", la vue de défilement deviendra défilante

ygweric
la source
2

Les personnes qui ont du mal avec uiscrollview qui ne font pas défiler définissent simplement la contrainte inférieure de votre vue de contenu avec la disposition inférieure de votre dernière vue (qui se trouve à l'intérieur de votre vue de contenu). N'oubliez pas de supprimer la contrainte Y centrale.

Reste que toutes les contraintes sont les mêmes que celles définies ci-dessus. Scrollview ne se préoccupe que d'obtenir la hauteur maximale de sa vue de contenu, et nous la définissons comme contrainte inférieure de la dernière vue, ce qui signifie que scrollview changera automatiquement son décalage de contenu.

Dans mon cas, la dernière vue était UILable sans aucune propriété de lignes = 0 (qui ajuste automatiquement sa hauteur en fonction de son contenu), ce qui augmente dynamiquement la hauteur de uilable et, finalement, notre zone de défilement augmente en raison de la disposition du bas de uilable est alignée avec le bas de notre vue de contenu, ce qui oblige scrollview à augmenter son décalage de contenu.

Siddhesh Mahadeshwar
la source
2

J'ai fait une vidéo sur
youTube Scroll StackViews en utilisant uniquement le Storyboard dans Xcode

Je pense que 2 types de scénarios peuvent apparaître ici.

La vue à l'intérieur du scrollView -

  1. n'a pas de contenu intrinsèque Taille (par exemple UIView)
  2. a son propre contenu intrinsèque Taille (par exemple UIStackView)

Pour une vue défilante verticalement dans les deux cas, vous devez ajouter ces contraintes:

  1. 4 contraintes de haut, gauche, bas et droite.

  2. Largeur égale à scrollview (pour arrêter le défilement horizontal)

Vous n'avez pas besoin d'autres contraintes pour les vues qui ont leur propre hauteur de contenu intrinsèque.

entrez la description de l'image ici


Pour les vues qui n'ont pas de hauteur de contenu intrinsèque, vous devez ajouter une contrainte de hauteur. La vue défilera uniquement si la contrainte de hauteur est supérieure à la hauteur de scrollView.

entrez la description de l'image ici

Warif Akhand Rishi
la source
2
import UIKit

class ViewController: UIViewController {

    //
    let scrollView: UIScrollView = {

        let sv = UIScrollView()
        sv.translatesAutoresizingMaskIntoConstraints = false
        return sv
    }()

    let lipsumLbl: UILabel = { // you can use here any of your subview

        let lbl = UILabel()
        lbl.translatesAutoresizingMaskIntoConstraints = false
        lbl.text = """
        Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce eleifend nisi sit amet mi aliquet, ut efficitur risus pellentesque. Phasellus nulla justo, scelerisque ut libero id, aliquet ullamcorper lectus. Integer id iaculis nibh. Duis feugiat mi vitae magna tincidunt, vitae consequat dui tempor. Donec blandit urna nec urna volutpat, sit amet sagittis massa fringilla. Pellentesque luctus erat nec dui luctus, sed maximus urna fermentum. Nullam purus nibh, cursus vel ex nec, pulvinar lobortis leo. Proin ac libero rhoncus, bibendum lorem sed, congue sapien. Donec commodo, est non mollis malesuada, nisi massa tempus ipsum, a varius quam lorem vitae nunc.

        Cras scelerisque nisi dolor, in gravida ex ornare a. Interdum et malesuada fames ac ante ipsum primis in faucibus. Maecenas vitae nisl id erat sollicitudin accumsan sit amet viverra sapien. Etiam scelerisque vulputate ante. Donec magna nibh, pharetra sed pretium ac, feugiat sit amet mi. Vestibulum in ipsum vitae dui vehicula pulvinar eget ut lectus. Fusce sagittis a elit ac elementum. Fusce iaculis nunc odio, at fermentum dolor varius et. Suspendisse consectetur congue massa non gravida. Sed id elit vitae nulla aliquam euismod. Pellentesque accumsan risus dolor, eu cursus nibh semper id.

        Vestibulum vel tortor tellus. Suspendisse potenti. Pellentesque id sapien eu augue placerat dictum. Fusce tempus ligula at diam lacinia congue in ut metus. Maecenas volutpat tellus in tellus maximus imperdiet. Integer dignissim condimentum lorem, id luctus nisi maximus at. Nulla pretium, est sit amet mollis eleifend, tellus nulla viverra dolor, ac feugiat massa risus a lectus. Pellentesque ut pulvinar urna, blandit gravida ipsum. Nullam volutpat arcu nec fringilla auctor. Integer egestas enim commodo, faucibus neque ac, rutrum magna. Vivamus tincidunt rutrum auctor. Cras at rutrum felis. Fusce elementum lorem ut pharetra venenatis.
        """
        lbl.textColor = .darkGray
        lbl.font = UIFont.systemFont(ofSize: 16)
        lbl.numberOfLines = 0
        return lbl
    }()

    //======================================================================//
    //
    // MARK:- viewDidLoad
    //
    override func viewDidLoad() {
        super.viewDidLoad()

        setupViews()
        setupAutoLayout()
    }

    func setupViews() {

        title = "ScrollView Demo"
        view.backgroundColor = .white
        view.addSubview(scrollView)
        scrollView.addSubview(lipsumLbl)
    }

    func setupAutoLayout() {

        scrollView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        scrollView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true

        lipsumLbl.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
        lipsumLbl.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
        lipsumLbl.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
        lipsumLbl.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
        lipsumLbl.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
    }
}

Production:

entrez la description de l'image ici

iAj
la source
Pourquoi avez-vous besoin de LeadingAnchor alors que vous avez déjà quitté Anchor?
ShadeToD
leftAnchor ne peut pas être utilisé à cette fin, nous devons donc utiliser LeadingAnchor pour y parvenir.
iAj
vous avez utilisé les deux dans votre exemple.
ShadeToD
@ShadeToD laissez-moi vérifier
iAj
2

Dans mon cas, j'ai reçu le problème de la taille du contenu et de l'ambiguïté de la taille du contenu sur l'iPad, mais je travaillais dans le cas de l'iPhone. J'ai effectué les modifications suivantes dans le storyboard pour résoudre le problème.

  1. Ajoutez scrollview dans UIView et ajoutez les contraintes de début, de haut, de fin et de bas à 0,0,0,0.
  2. Réglez la hauteur de la vue de défilement selon les exigences, par exemple. 100.
  3. Ajoutez UIView pour faire défiler la vue et ajoutez les contraintes de début, de haut, de fin et de bas à 0,0,0,0 et alignez les contraintes centrales (X) et centrales (Y).
  4. Désélectionnez «Content Layout Guides» dans l'inspecteur de taille de la vue de défilement.
Daljeet Seera
la source
1

Défilement vertical

  1. Ajoutez un UIScrollView avec des contraintes 0,0,0,0 à la vue d'ensemble.
  2. Ajoutez une UIView dans ScrollView, avec les contraintes 0,0,0,0 à superview.
  3. Ajoutez la même contrainte de largeur pour UIView à UIScrollView.
  4. Ajoutez la hauteur à UIView.
  5. Ajoutez des éléments avec des contraintes à l'UIView.
  6. Pour l'élément le plus proche du bas, assurez-vous qu'il a une contrainte au bas de UIView.
Bitcon
la source
0

Ce que j'ai fait, c'est créer une vue de contenu séparée, comme indiqué ici.

La vue de contenu est de forme libre et peut contenir toutes les sous-vues avec leurs propres contraintes par rapport à la contentView.

UIScrollView est ajouté au contrôleur de vue principal.

J'ajoute par programme le contentView qui est lié via IBOutlet à la classe et définit le contentView de UIScrollView.

UIScrollView avec ContentView via Interface Builder

Vlad
la source
0

J'obtenais la même erreur .. j'ai fait suivant

  1. Vue (Superview)
  2. ScrollView 0,0,600,600
  3. UIView dans ScrollView: 0,0,600,600
  4. UIView contient une vue d'image, une étiquette

Ajoutez maintenant le début / fin / haut / bas pour scrollView (2) puis UIView (3).

Sélectionnez Affichage (1) et Affichage (3) définissez également la taille et le poids .. son résolu mon problème.

J'ai fait la vidéo qui vous aidera:

https://www.youtube.com/watch?v=s-CPN3xZS1A

Vinod Joshi
la source
0

[testé dans XCode 7.2 et pour iOS 9.2]

Ce qui a supprimé les erreurs et les avertissements du Storyboard pour moi était de définir la taille intrinsèque de la vue de défilement et de la vue de contenu (dans mon cas, une vue de pile) sur Placeholder . Ce paramètre se trouve dans l'inspecteur de taille dans Storyboard. Et cela dit - La définition d'une taille de contenu intrinsèque au moment de la conception affecte uniquement une vue lors de la modification dans Interface Builder. La vue n'aura pas cette taille de contenu intrinsèque lors de l'exécution.

Donc, je suppose que nous ne nous trompons pas en réglant cela.

Remarque: Dans le storyboard, j'ai épinglé tous les bords de scrollview à la vue d'ensemble et tous les bords de stackview à la scrollview. Dans mon code, j'ai défini les translatesAutoresizingMaskIntoConstraints comme faux pour la vue de défilement et la vue de pile. Et je n'ai pas mentionné de taille de contenu. Lorsque la vue de la pile se développe dynamiquement, les contraintes définies dans le storyboard garantissent que la pile peut défiler.

L'avertissement du storyboard me rendait fou et je ne voulais pas centrer les choses horizontalement ou verticalement juste pour supprimer l'avertissement.

gtl_pm
la source
0

Si quelqu'un obtient un comportement où vous remarquez la barre de défilement sur les rouleaux de droite mais le contenu ne bouge pas, ce fait mérite probablement d'être pris en considération:

Vous pouvez également utiliser des contraintes entre le contenu de la vue de défilement et les objets en dehors de la vue de défilement pour fournir une position fixe pour le contenu de la vue de défilement, ce qui semble flotter sur la vue de défilement.

Cela vient de la documentation d'Apple . Par exemple, si vous épingliez accidentellement votre étiquette / bouton / img / vue supérieur à la vue en dehors de la zone de défilement (peut-être un en-tête ou quelque chose juste au-dessus de scrollView?) Au lieu de contentView, vous feriez tout votre contentView en place.

Dave G
la source
0

Comme mentionné dans les réponses précédentes, vous devez ajouter une vue personnalisée dans la vue de défilement:

La vue personnalisée est le ContentView marqué dans l'image

Ajoutez toutes vos sous-vues à la vue du contenu. À un moment donné, vous verrez une vue de contenu de défilement avec un avertissement de taille de contenu ambigu, vous devez sélectionner la vue de contenu et cliquer sur le bouton "Résoudre les problèmes de mise en page automatique" (dans le coin inférieur droit de la mise en page IB), puis sélectionner "Ajouter manquant contraintes ".

entrez la description de l'image ici

À partir de maintenant, lorsque vous exécutez le projet, la vue de défilement mettra automatiquement à jour sa taille de contenu, aucun code supplémentaire n'est nécessaire.

supergegs
la source
0

Il vous suffit de vous assurer qu'il existe un moyen de créer une ligne continue de contraintes du haut vers le bas de la vue de défilement. [-XXX]

Dans mon cas - une vue de défilement horizontal - j'ai également dû ajouter des contraintes de largeur et de hauteur pour chaque enfant de la vue de défilement, bien que la note technique d'Apple ne vous le dise pas.

johnnyMac
la source
0

Si vous avez encore des problèmes avec UIScrollView, juste désactiver le contenu mise en page Guides (Choisissez votre ScrollView dans Xcode Interface Builder -> choisissez Inspecteur Taille dans le panneau droit -> deselect 'Contenu Guides de mise en page) ou essayez ces étapes: Xcode 11 défilement des mises en page de vue - il peut être utile pour un nouveau style de mise en page. Fonctionne bien sous macOS 10.15.2, Xcode 11.3.1, pour 05.02.2020

voir capture d'écran

Victor Doshenko
la source
0

Utilisation de la mise en page automatique

Ajoutez votre vue de défilement dans une vue bien définie, puis ajoutez la vue de pile dans la vue de défilement

Ajoutez des contraintes en haut, à gauche, à droite, en bas, au centre X et au centre Y de la vue de défilement et de la vue de pile à leurs super vues pertinentes

Assurez-vous que les contraintes sont liées de la vue de la pile à la vue d'ensemble légitime (scrollview) car le paramètre par défaut actuel consiste à ajouter une contrainte Aligner en haut et non pas une espace en haut.

Ahmed Elashker
la source