web-dev-qa-db-fra.com

Désactiver le défilement horizontal dans UIScrollView avec autolayout

Je veux créer une vue avec uniquement un défilement vertical. Comme il s’est avéré que c’est difficile à faire dans les organisations d’entreprise. J'ai fait cette étape:

1) Créer UIViewController dans le storyboard;

2) Ajoutez ScrollView dans la vue dans UIViewController et ajoutez 0 contrainte à chaque côté.

3) Ajouter des éléments dans scrollview, comme résultat:  enter image description here

Après avoir lancé mon application, tout fonctionne, mais:

1) Comment dois-je désactiver le défilement horizontal? J'ajoute 0 contraindre à droite à mon scrollView + 0 contraindre à droite à mon uilabel (comme vous le voyez à l'écran pour certaines raisons, il n'est pas attaché à droite, il a une contrainte différente, mais dans la propriété j'ai mis constrain = 0) et, comme je le pensais, le texte de l'étiquette est supposé se trouver dans les limites de mon écran, mais lorsque je lance une application, je peux faire défiler vers la droite, c.-à-d. que le texte uilable ne s'est pas enveloppé, ma vue de défilement a juste été redimensionnée pour s'adapter au texte. dans le code: scrollView.contentSize = CGSize(UIScreen.mainScreen().bounds.width, height: 800), mais n'a pas aidé.

2) Si je défile trop, un espace apparaît et ce n’est pas cool, comment le réparer?

19
Panich Maxim

1) Le défilement horizontal est activé automatiquement lorsque la largeur du contenu dans scrollView dépasse la largeur de scrollView. Par conséquent, afin d'éviter le défilement horizontal, il est nécessaire de rendre la largeur du contenu à l'intérieur de scrollView inférieure ou égale à la largeur de scrollView.

Leading space et trailing space ne peuvent pas définir de largeur spécifique pour les vues, ils les étirent simplement. Dans les vues normales, elles ne s'étirent pas plus que la largeur de la vue, mais scrollView est une vue spéciale, avec une largeur de contenu infinie. Par conséquent, les contraintes trailing space et leading space dans scrollView modifient la largeur des vues sur leur valeur maximale possible (dans le cas où UILabel vous permet d'afficher un redimensionnement adapté au texte).

Pour éviter le défilement horizontal, vous devez définir une largeur spécifique pour chaque vue, inférieure ou égale à la largeur de scrollView. La largeur spécifique des vues peut être définie avec width constraints.

Au lieu de définir chaque largeur de vue, il est préférable d’ajouter un conteneur de vues et de lui définir la largeur, puis de placer les vues à la place.

Hiérarchie des vues:

View
    -> ScrollView
        -> ContainerView
            -> UILabel
            -> UILabel
            -> ... other views that you need

Contraintes de retrait automatique:

ScrollView
    -> leading space to View : 0
    -> trailing space to View : 0
    -> top space to View : 0
    -> bottom space to View : 0

Container View
    -> leading space to ScrollView : 0
    -> trailing space to ScrollView : 0
    -> top space to ScrollView : 0
    -> bottom space to ScrollView : 0
    -> width equal to ScrollView : 0

Pour définir width equal constraintctrl + glisser de containerView à scrollView.

 width equal constraint

2) Le défilement vertical dépend de la hauteur totale du contenu. Un espace peut être vide si le dernier élément de containerView a une grande valeur de bottom space to superview.

Ou voulez-vous dire l'effet de rebond? Vous pouvez désactiver le rebond vertical de scrollView.

58
ifau

Vous pouvez également le faire facilement dans le code. Dans mon cas, j'ai une UIStackView qui est la seule sous-vue d'une UIScrollView

// Create the stack view
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
// Add things to the stack view....

// Add it as a subview to the scroll view
scrollView.addSubview(stackView)

// Use auto layout to pin the stack view's sides to the scroll view
NSLayoutConstraint.activate([
    stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
    scrollView.trailingAnchor.constraint(equalTo: stackView.trailingAnchor),

    stackView.topAnchor.constraint(equalTo: scrollView.topAnchor),
    scrollView.bottomAnchor.constraint(equalTo: stackView.bottomAnchor)
])

// Now make sure the thing doesn't scroll horizontally
let margin: CGFloat = 40

scrollView.contentInset = UIEdgeInsets(top: margin, left: margin, bottom: margin, right: margin)

scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true

let stackViewWidthConstraint = stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
stackViewWidthConstraint.constant = -(margin * 2)
stackViewWidthConstraint.isActive = true

Le bit NSLayoutConstraint.activate provient de l'excellente extension UIView de Dave DeLong ici: https://github.com/davedelong/MVCTodo/blob/master/MVCTodo/Extensions/UIView.Swift#L26

0