624 votes

Ambiguïté sur la taille du contenu défilant de UIScrollView

Amis 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. Si c'est un bug dans Xcode, c'est un bug critique !

Ainsi, 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)

L'UIScrollView a des contraintes solides, par exemple 50 px de chaque côté (pas de problème). Ensuite, j'ajoute une contrainte d'espace supérieur à l'UILabel (aucun problème) (et je peux même épingler la hauteur/largeur de l'étiquette, ce qui 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 est égal à : 25

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

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

B) Vues déplacées (étiquette) Attendu : x= -67 Réel : x= 207

J'ai fait cet exemple minimal dans un tout nouveau projet que vous pouvez télécharger et dont j'ai joint une capture d'écran. Comme vous pouvez le voir, Interface Builder s'attend à ce que l'étiquette se trouve à l'extérieur des limites de l'UIScrollView (le rectangle en pointillés orange). La mise à jour du cadre de l'étiquette à l'aide de l'outil Resolve Issues la déplace à cet endroit.

Remarque : si vous remplacez UIScrollView par un 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 quelque chose d'important m'échappe.

Lorsque j'exécute l'application sans mettre à jour le cadre de l'étiquette, comme le suggère IB, l'étiquette est bien positionnée, exactement là où elle est censée être et l'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 of the problem in Interface Builder

9 votes

Essayez de placer l'UILabel dans une vue de contenu, puis de définir le bord arrière de l'étiquette sur la vue de contenu (UIView normale). Cette vidéo peut vous aider grandement : youtube.com/watch?v=PgeNPRBrB18&feature=youtu.be

1 votes

Superbe vidéo, mais les avertissements n'ont pas été corrigés pour moi.

0 votes

Merci beaucoup pour la vidéo - j'ai appris beaucoup de choses (de façon assez surprenante) ! Cependant, lorsque j'associe les connaissances de la vidéo à celles de l'ordinateur, j'ai l'impression de ne pas être à la hauteur. stackoverflow.com/questions/18953617/ Je peux corriger les avertissements. La question qui reste est la suivante : Comment faire en sorte que la taille de la ContentView du scrollView ne soit pas plus grande que nécessaire ?

104voto

self.name Points 773

Cette erreur m'a pris un certain temps à trouver. Au départ, j'ai essayé d'épingler la taille de la ScrollView, mais le message d'erreur indique clairement "taille du contenu". J'ai fait en sorte que tout ce que j'ai épinglé en haut de la ScrollView soit également épinglé en bas. De cette façon, le ScrollView peut calculer la hauteur de son contenu en trouvant la hauteur de tous les objets et contraintes. Cela a résolu l'ambiguïté de la hauteur du contenu, la largeur est assez similaire... Au départ, la plupart des éléments étaient centrés en 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 'ambiguous content width'.

33 votes

Merci pour votre réponse ! Si je comprends bien, vous parvenez à supprimer l'erreur en épinglant chaque sous-vue du ScrollView en haut et en bas. Cependant, ce n'est pas nécessaire. Vous devez simplement vous assurer qu'il existe un moyen de créer une ligne continue de contraintes du haut vers le bas du ScrollView. [J'espère que c'était compréhensible ;-)

2 votes

Comment résoudre le problème si la vue a une hauteur variable ? Comment configurer les contraintes pour que le scrollview puisse calculer les tailles ?

0 votes

@hashier Je pense que si le scrollview est de hauteur variable, il n'y a pas de problème car cet avertissement est lancé au moment de la conception, mais n'affecte pas l'exécution de votre application. Un scrollview à hauteur variable doit avoir redimensionné son contentSize par code.

65voto

skywinder Points 1035

C'est la réponse à la question que je me suis posée. UIScrollView + Vue centrée + Taille du contenu défilant ambigüe + plusieurs tailles d'iPhone .

Mais il couvre entièrement votre cas aussi !

Donc, voici l'état initial pour le cas le plus simple :

  1. scrollView avec 0 contrainte sur tous les bords
  2. Bouton centrée Horizontale et Verticale con Largeur et hauteur fixes contraintes
  3. Et, bien sûr. avertissements gênants Has ambiguous scrollable content width y Has ambiguous scrollable content height .

1

Tout ce que nous avons à faire, c'est :

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

Important : vous devez ajouter arrière et/ou bas contraintes. Pas de "leading and top" - ce n'est pas du travail !

2

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

P.S.

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

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

0 votes

Bon conseil ! J'ai fini par créer une contrainte sur le bord inférieur et par définir une priorité moyenne ou faible.

0 votes

Wow ! Cela n'a vraiment aucun sens, mais ça marche ! Merci ! Le dernier élément que j'ai dans ma vue, j'ai défini une contrainte inférieure de 0, et BANG. Ça a enfin marché.

54voto

Thiago Monteiro Points 11

Vous devez créer un UIView comme une sous-vue de la UIScrollView comme décrit ci-dessous :

  • UIViewController
  • UIView Vue principale
    • UIScrollView
      • UIView Vue du conteneur
        • [Votre contenu]

La deuxième étape consiste à faire le UIScrollView contraintes. Je l'ai fait avec les contraintes de haut, de bas, de tête et de queue de sa super-vue.

Ensuite, j'ai ajouté les contraintes pour le conteneur de UIScrollView et c'est là que le problème commence. Lorsque vous mettez les mêmes contraintes (haut, bas, avant et arrière) le Storyboard donne un message d'avertissement :

"A une largeur de contenu défilable ambiguë" et "A une hauteur de contenu défilable ambiguë".

Continuez avec les mêmes contraintes ci-dessus, et ajoutez simplement les contraintes Equal Height y Equal Width à votre Vue du conteneur en relation avec le Vue principale y pas à votre UIScrollView . En d'autres termes, les contraintes de la vue du conteneur sont liées à la vue du conteneur. UIScrollView La vue supérieure de l'entreprise.

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

2 votes

Je suis d'accord - je pense que l'ajout d'une vue conteneur est la meilleure solution, la plus facile à maintenir.

1 votes

Cette solution fonctionnera si vous n'avez pas de barre de navigation à gérer.

6voto

Mike Simz Points 375

Jetez un coup d'œil à ce tutoriel rapide et concis sur la façon de faire fonctionner la vue défilante 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 défilante est toujours plus grande que nécessaire

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

2voto

ADG Points 11

Je pense que ce tutoriel a la réponse :

http://spin.atomicobject.com/2014/03/05/uiscrollview-autolayout-ios/

Il montre, étape par étape, comment gérer la situation de scrollview.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X