web-dev-qa-db-fra.com

Utilisation de la vue par défilement avec Autolayout Swift

Je sais que cette question a été posée à maintes reprises, mais c’est un problème avec lequel je me bats depuis longtemps et je suis sûr que d’autres le sont aussi, même avec les réponses et les tutoriels actuels.

Lors de l'ajout d'une vue de défilement, je passe par les étapes suivantes:

  1. Ajoutez une vue de défilement en tant que sous-vue de la vue d'origine dans le contrôleur de vue. Épinglez en haut, à gauche, à droite et en bas. S'assurer que "Contraindre aux marges" n'est pas coché.

  2. Ajoutez un UIView en tant que sous-vue de la vue Défilement. Épinglez les contraintes en haut, à gauche, à droite et en bas. 

  3. Ajoutez une contrainte d'égale largeur entre la vue de contenu et la vue des contrôleurs de vue.

À ce stade de l'exécution de l'application, la vue du contenu ne s'affiche pas et la vue en défilement occupe tout l'écran.

  1. Ensuite, j'ajoute à la vue du contenu des éléments qui incluent uniquement 4 UIViews pour tout tester. Je donne à chaque UIView des contraintes de haut, de gauche et de droite. Et le dernier UIV a vu une contrainte inférieure.

Pas à ce stade, lorsque j'exécute l'application, les options Affichage du contenu et Affichage du défilement occupent environ la moitié de l'écran et je peux faire défiler l'affichage du contenu. Voir la photo ci-dessous.

J'ai suivi tous les tutoriels que je pouvais trouver et essayé d'appliquer toutes les réponses SO que j'ai trouvées mais je n'arrive pas à le faire fonctionner. Si quelqu'un le découvre ou connaît une solution, votre aide sera grandement appréciée!

Le vert est la vue du contenu et le bleu est la vue du défilement.

 enter image description here

Défilement de vue et sous-vue

 enter image description here

14
m1234

J'ai compris cela avec l'aide des autres réponses, mais j'ai dû faire quelques ajustements pour que tout fonctionne comme je le voulais. Voici les étapes que j'ai prises:

  1. Ajouter une vue de défilement en tant que vue secondaire de la vue principale.

  2. Sélectionnez la vue Défilement et décochez la case "Contraindre aux marges" et épinglez les contraintes haut, gauche, droite, bas

  3. Ajoutez un UIView en tant que sous-vue de la vue Défilement. Nommez cette vue "Vue du contenu"

  4. Sélectionnez la vue Contenu et épinglez les contraintes en haut, à gauche, à droite et en bas. Ajoutez ensuite une contrainte de centre horizontalement.

  5. Suivant de la vue Contenu à la vue principale, ajoutez des contraintes d'égale largeur et d'égale hauteur.

  6. Ajoutez tous les éléments dont vous avez besoin dans la vue Contenu. Épinglez les contraintes de haut, de gauche, de droite et de hauteur sur les éléments que vous venez d'ajouter.

  7. Sur l'élément le plus en bas de la vue Contenu, épinglez une contrainte en bas. Sélectionnez cette contrainte et passez à "Supérieur ou égal à". Remplacez la constante par 20.

Les contraintes ajoutées aux éléments à l'intérieur de la vue Contenu sont très importantes, en particulier la contrainte inférieure ajoutée au dernier élément. Ils aident à déterminer la taille du contenu de la vue de défilement. L'ajout de la contrainte inférieure comme je l'ai décrit permettra à la vue de défiler si le contenu est trop volumineux pour tenir sur l'écran et désactivera le défilement si le contenu s'adapte à l'écran.

50
m1234

J'ai créé une vue simple en code qui devrait être explicite et qui pourrait vous aider. Il décrit toutes les étapes à suivre pour que la vue par défilement fonctionne. 

Si quelque chose n'est pas clair, n'hésitez pas à laisser un commentaire.

import UIKit

class TutorialView: UIView {

    lazy var sv: UIScrollView = {
        let object = UIScrollView()

        object.backgroundColor = UIColor.whiteColor()
        object.translatesAutoresizingMaskIntoConstraints = false
        return object
    }()

    lazy var tutorialPageOne: UIView = {
        let object = UIView(frame: UIScreen.mainScreen().bounds)
        object.translatesAutoresizingMaskIntoConstraints = false
        object.backgroundColor = UIColor.cyanColor()

        return object
    }()

    lazy var tutorialPageTwo: UIView = {
        let object = UIView(frame: UIScreen.mainScreen().bounds)
        object.translatesAutoresizingMaskIntoConstraints = false
        object.backgroundColor = UIColor.lightGrayColor()

        return object
    }()

    lazy var tutorialPageThree: UIView = {
        let object = UIView(frame: UIScreen.mainScreen().bounds)
        object.translatesAutoresizingMaskIntoConstraints = false
        object.backgroundColor = UIColor.redColor()

        return object
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)

        self.addSubview(self.sv)
        self.sv.addSubview(self.tutorialPageOne)
        self.sv.addSubview(self.tutorialPageTwo)
        self.sv.addSubview(self.tutorialPageThree)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        let vc = nextResponder() as? UIViewController
        let mainSreenWidth = UIScreen.mainScreen().bounds.size.width
        let mainScreenHeight = UIScreen.mainScreen().bounds.size.height

        NSLayoutConstraint.activateConstraints([
            self.sv.topAnchor.constraintEqualToAnchor(vc?.topLayoutGuide.bottomAnchor),
            self.sv.leadingAnchor.constraintEqualToAnchor(self.leadingAnchor),
            self.sv.bottomAnchor.constraintEqualToAnchor(vc?.bottomLayoutGuide.topAnchor),
            self.sv.trailingAnchor.constraintEqualToAnchor(self.trailingAnchor)
        ])

        NSLayoutConstraint.activateConstraints([
            self.tutorialPageOne.widthAnchor.constraintEqualToConstant(mainSreenWidth),
            self.tutorialPageOne.heightAnchor.constraintEqualToConstant(mainScreenHeight),
            self.tutorialPageOne.topAnchor.constraintEqualToAnchor(self.sv.topAnchor),
            self.tutorialPageOne.leadingAnchor.constraintEqualToAnchor(self.sv.leadingAnchor),
            self.tutorialPageOne.bottomAnchor.constraintEqualToAnchor(self.sv.bottomAnchor)
        ])


        NSLayoutConstraint.activateConstraints([
            self.tutorialPageTwo.widthAnchor.constraintEqualToConstant(mainSreenWidth),
            self.tutorialPageTwo.heightAnchor.constraintEqualToConstant(mainScreenHeight),
            self.tutorialPageTwo.topAnchor.constraintEqualToAnchor(self.sv.topAnchor),
            self.tutorialPageTwo.leadingAnchor.constraintEqualToAnchor(self.tutorialPageOne.trailingAnchor),
            self.tutorialPageTwo.bottomAnchor.constraintEqualToAnchor(self.sv.bottomAnchor)
        ])

        NSLayoutConstraint.activateConstraints([
            self.tutorialPageThree.widthAnchor.constraintEqualToConstant(mainSreenWidth),
            self.tutorialPageThree.heightAnchor.constraintEqualToConstant(mainScreenHeight),
            self.tutorialPageThree.topAnchor.constraintEqualToAnchor(self.sv.topAnchor),
            self.tutorialPageThree.leadingAnchor.constraintEqualToAnchor(self.tutorialPageTwo.trailingAnchor),
            self.tutorialPageThree.bottomAnchor.constraintEqualToAnchor(self.sv.bottomAnchor),
            self.tutorialPageThree.trailingAnchor.constraintEqualToAnchor(self.sv.trailingAnchor)
        ])

    }
}
4
Tomasz Nazarenko

Pour ceux qui recherchent un exemple UIScrollView et AutoLayout. J'utilise SnapKit, cela fonctionne pour Xcode 9, Swift 3

    let scrollView = UIScrollView()
    view.addSubview(scrollView)
    scrollView.snp.makeConstraints { (make) in
        make.edges.equalTo(view).inset(UIEdgeInsetsMake(0, 0, 0, 0))
        make.top.left.right.equalTo(view)
    }

    let view1 = UIView()
    view1.backgroundColor = UIColor.red
    scrollView.addSubview(view1)
    view1.snp.makeConstraints { (make) in
        make.top.equalTo(scrollView.snp.top).offset(0)
        make.left.equalTo(scrollView.snp.left).offset(0)
        make.width.equalTo(scrollView.snp.width)
        make.height.equalTo(300)
    }

    let view2 = UIView()
    view2.backgroundColor = UIColor.blue
    scrollView.addSubview(view2)
    view2.snp.makeConstraints { (make) in
        make.top.equalTo(view1.snp.bottom)
        make.left.equalTo(scrollView)
        make.width.equalTo(scrollView)
        make.height.equalTo(300)
    }

    let view3 = UIView()
    view3.backgroundColor = UIColor.green
    scrollView.addSubview(view3)
    view3.snp.makeConstraints { (make) in
        make.top.equalTo(view2.snp.bottom)
        make.left.equalTo(scrollView)
        make.width.equalTo(scrollView)
        make.height.equalTo(100)
        make.bottom.equalTo(scrollView.snp.bottom).offset(-20)
    }
2
nmh

J'ai passé beaucoup de temps à comprendre cela et c'est assez simple. Voici la solution. Suivez ces étapes

  • Ajouter ScrollView en tant que sous-vue de la vue principale
  • Épinglez haut, gauche, droite, bas, horizontalement dans le conteneur, verticalement dans le conteneur.
  • Ajouter un conteneur en tant que sous-vue du défilement
  • Épinglez haut, gauche, droite, bas, horizontalement dans le conteneur, verticalement dans le conteneur.
  • Ajoutez vos sous-vues en vue conteneur avec les contraintes souhaitées.
  • Définissez la taille du contenu de la vue de défilement en conséquence.

Poursuivre le défilement :) 

2
Fahad Azeem

Suivez ces étapes:

  1. Ajouter une vue de défilement en tant que vue secondaire de la vue principale.
  2. Sélectionnez la vue Défilement et décochez la case "Contraindre aux marges" et épinglez les contraintes haut, gauche, droite, bas
  3. Ajoutez un UIView en tant que sous-vue de la vue Défilement. Nommez cette vue "Vue du contenu"
  4. Définissez la contrainte «Vue du contenu» (haut, bas, premier et dernier) comme (0,0,0,0).
  5. Vous pouvez maintenant voir la hiérarchie comme celle-ci -> vue défilement -> vue (vue contenu)
  6. Notre «vue Contenu» doit avoir une largeur égale et une hauteur égale avec la vue parent.
  7. Sélectionnez contrainte de hauteur de la vue du contenu et définissez priorité avec bas (250) .
  8. Vous pouvez maintenant concevoir votre vue avec n’importe quelle hauteur.
  9. Ajoutez tous les éléments dont vous avez besoin dans Vue du contenu . Épingler haut, gauche, droite et hauteur contraintes aux éléments qui viennent d'être ajoutés.
  10. Félicitations, vous avez terminé avec la vue de défilement avec autolayout.
2
Sahdevsinh Chavda

Je veux juste montrer visuellement ... Si vous voulez créer une vue plus grande que la taille de ViewController, vous pouvez augmenter la hauteur de l'inspecteur de taille de formulaire de ViewController. Choisissez la taille simulée à la forme libre et définissez la hauteur requise comme indiqué dans l'image. Votre viewController a maintenant la hauteur mentionnée.

 enter image description here

  1. Faites glisser Scrollview dans votre ViewController et appliquez quatre contraintes (Début, Fin, Haut et Bas)  enter image description here

  2. Maintenant, faites glisser une vue ayant la même largeur et la même hauteur que ScrollView dans ScrollView et définissez 6 contraintes (Avant, Fin, Haut, Bas, FixHeight, = WidthToScrollView). Dans mon cas, j'ai 15 espaces L et T et d'autres marges en conséquence. Votre vue peut avoir une marge différente mais les contraintes doivent être identiques.

 enter image description here .  enter image description here

  1. Vous pouvez maintenant faire glisser vos vues en conséquence et définir des contraintes. J'ai deux vues à l'intérieur de la vue.

 enter image description here

  1. Pour la 1ère vue, je règle Leading, Top, Trailing et je veux avoir une hauteur fixe. Pour la deuxième fois, je règle Début, Bas, Dernier et je veux avoir une hauteur fixe.

 enter image description here .  enter image description here

  1. Félicitation! Vous avez tous mis maintenant exécuter votre application.

 enter image description here  enter image description here

1
GSK

La meilleure façon de créer une interface utilisateur dans un scrollView sans code est la suivante: 

  1. Ajoutez votre scrollView à uiviewcontroller avec les contraintes appropriées entre celui-ci et sa vue parent.
  2. Ajouter une "vue d'accolade" à la vue de défilement.
  3. La "vue d'accolade" doit être masquée car elle ne fait pas partie de votre interface utilisateur finale.
  4. Faire à gauche, en haut et à droite contient entre “vue d'accolade” et le UIScrollView. Faire une contrainte de hauteur. (La contrainte de hauteur peut être n'importe quel nombre). Alignez le centre x sur les contraintes UIScrollView.

  5. Ajoutez votre interface utilisateur finale sous la "vue d'accolade".

  6. Ajouter une contrainte supérieure entre la première vue de l'interface utilisateur finale et la «vue d'accolade».
  7. Liez toutes les vues de votre interface utilisateur finale aux contraintes du haut ou du bas.
  8. Ajoutez les contraintes d’interface utilisateur finales appropriées.
  9. Ajoutez des contraintes inférieures entre la dernière vue de l'interface utilisateur finale et la vue de défilement. (Cette contrainte.constant est importante car elle fait partie de votre interface utilisateur finale).

Voici un rapide projet github exemple. 

 enter image description here  enter image description here

0
Randel G. Smith

La classe UIScrollView fait défiler son contenu en modifiant l'origine de ses limites. Pour que cela fonctionne avec la disposition automatique, les bords supérieur, gauche, droit et à l'intérieur d'une vue de défilement désignent maintenant les bords de sa vue de contenu.

Les contraintes sur les sous-vues de la vue de défilement doivent donner une taille à remplir, qui est ensuite interprétée comme la taille du contenu de la vue de défilement. (Ceci ne doit pas être confondu avec la méthode intrinsèqueContentSize utilisée pour la présentation automatique.) Pour redimensionner le cadre de la vue de défilement avec Mise en forme automatique, les contraintes doivent être explicites en ce qui concerne la largeur et la hauteur de la vue de défilement ou les bords de la vue de défilement lié à des vues à l'extérieur de son sous-arbre.

Voir aussi une note technique que Apple a écrite sur ce problème: https://developer.Apple.com/library/ios/technotes/tn2154/_index.html

0
Joride

Selon @ m1234, vous devez toutefois libérer les hauteurs égales, sinon le parchemin ne fonctionne pas - ma méthode serait la suivante:

  1. Ajouter une vue de défilement en tant que vue secondaire de la vue principale.

  2. Sélectionnez la vue Défilement et décochez la case "Contraindre aux marges" et épinglez les contraintes haut, gauche, droite, bas

  3. Ajoutez un UIView en tant que sous-vue de la vue Défilement. Nommez cette vue "Vue du contenu"

  4. Sélectionnez la vue Contenu et épinglez les contraintes en haut, à gauche, à droite et en bas. Ajoutez ensuite une contrainte de centre horizontalement.

  5. Suivant de la vue Contenu à la vue principale, ajoutez une contrainte de largeur égale.

  6. Ajoutez tous les éléments dont vous avez besoin dans la vue Contenu. Épinglez les contraintes de haut, de gauche, de droite et de hauteur sur les éléments que vous venez d'ajouter.

  7. Sur l'élément le plus en bas de la vue Contenu, épinglez une contrainte en bas. Sélectionnez cette contrainte et passez à "Supérieur ou égal à". Remplacez la constante par 20.

0
Bowcaps