web-dev-qa-db-fra.com

Swift UIScrollView - Implémentation correcte pour le défilement vertical uniquement

En avance, je m'excuse car je dirais que je suis un débutant en programmation iOS.

Je souhaite utiliser UIScrollView car le contenu à afficher dépasse la hauteur de l'écran . Par conséquent, je souhaite uniquement un défilement vertical et non un défilement horizontal.

J'utilise le Storyboard pour dessiner les vues avec AutoLayout.

Voici la capture d'écran de ma UIViewController avec la UIScrollView:

enter image description hereenter image description here

Puis je change le libellé en un gros texte comme celui-ci

override func viewDidLoad() {
    super.viewDidLoad()

    self.label1Label.text = "Seize jours après la chute du président Blaise Compaoré, le Burkina Faso a un nouveau chef d'EtatA l'issue d'ultimes tractions, civils et militaires se sont accordés, lundi 17 novembre, sur le nom du diplomate Michel KafandoSeize jours après la chute du président Blaise Compaoré, le Burkina Faso a un nouveau chef d'EtatA l'issue d'ultimes tractions, civils et militaires se sont accordés, lundi 17 novembre, sur le nom du diplomate Michel Kafando"
    self.label1Label.numberOfLines = 0
    self.label1Label.sizeToFit()

Mon problème est que si je ne définit pas manuellement la largeur de mon contentView (dans la variable UIScrollView), le défilement est horizontal et non vertical. (Regardez la capture d'écran ci-dessous):

enter image description here

J'ai essayé de définir contentSize comme je l'ai vu dans de nombreuses publications sur Google, mais sans succès:

self.scrollView.contentSize = CGSizeMake(400.0, 600.0)

Si je règle manuellement la largeur de mon contentview (i.e : 320pts), le défilement sera vertical (BON), mais selon la taille de l'iphone, il ne couvrira pas toute la largeur de l'écran, comme illustré dans la capture d'écran suivante:

enter image description here

La question qui se pose est la suivante: quelle est la bonne implémentation pour utiliser UIScrollView afin d’avoir une contentView qui respecte la contrainte autolayout (full screen : 0top - 0bottom - 0left - 0right) et que le défilement soit uniquement vertical.

Merci beaucoup pour votre aide!

14
fabdarice

Mike Woelmer montre comment procéder correctement avec Interface Builder sur le blog Atomic Object. 

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

J'ai aussi mon propre code uniquement (pas d'implémentation de storyboard) sur github.

https://github.com/nadthevlad/AutolayotScrollview

Vous ne souhaitez pas définir la hauteur ou la largeur de votre contenu ou de vos vues. Au lieu de cela, vous souhaitez utiliser des épingles et des contraintes d’autolayouts pour définir le comportement de scrollview. 

  1. Créez votre scrollView UIScrollView *.

  2. Vous souhaitez créer un UViewView * contentView dans lequel vous allez placer le reste de vos éléments de vue.

    [self.view addSubview:scrollView];
    [scrollView addSubview:contentView];
    [contentView addSubview:_label1];
    [contentView addSubview:_label2];
    [contentView addSubview:_label3];
    [contentView addSubview:_label4];
    [contentView addSubview:_label5];
    [contentView addSubview:_label6];
    
  3. Épinglez les 4 bords de scrollView sur les 4 bords de self.view

  4. Épinglez les bords supérieur et inférieur de contentView en haut et en bas de scrollView.

  5. C'est la partie la plus délicate. Pour définir la taille horizontale, vous voulez que les bords avant (droit) et arrière (gauche) de contentView soient épinglés aux bords avant et arrière self.view au lieu de scrollView. Même si contenView est une sous-vue de scrollView, ses contraintes horizontales vont aller au-delà de scrollView et se connecter à self.view.

  6. Épinglez tous les autres éléments de vue à contentView comme vous le feriez normalement. 

38
NadtheVlad

L'astuce pour permettre à UIScrollView de défiler dans une seule direction consiste à rendre la taille du contenu de UIScrollView pour la dimension restreinte identique à la taille du cadre d'UIScrollView dans la même dimension. Donc, dans ce cas, scrollview.contentSize.width devrait être égal à scrollview.frame.size.width.

Dans cet esprit, essayez ce qui suit:

  1. Assurez-vous que les contraintes sont configurées de la manière décrite dans cette réponse

  2. Ajoutez le code suivant à votre contrôleur de vue:

    override func viewWillLayoutSubviews()
    {
        super.viewWillLayoutSubviews();
        self.scrollView.contentSize.height = 3000; // Or whatever you want it to be.
    }
    

Personnellement, je ne suis vraiment pas un fan de la mise en page automatique. Si vous êtes intéressé à essayer ceci sans mise en page automatique - c'est-à-dire. juste avec du code au lieu de contraintes - vous pouvez désactiver la mise en page automatique pour la vue du contrôleur de vue et changer votre méthode viewWillLayoutSubviews pour qu'elle ressemble à ceci:

override func viewWillLayoutSubviews()
{
    super.viewWillLayoutSubviews();

    self.scrollView.frame = self.view.bounds; // Instead of using auto layout
    self.scrollView.contentSize.height = 3000; // Or whatever you want it to be.
}
20
gavdotnet

Voici comment je le fais toujours pour le défilement vertical du storyboard avec des contraintes: 

1-glisser un contrôleur de vue 

2, faites glisser une vue de défilement dans la vue principale du contrôleur avec les contraintes L = 0, T = 0, T = 0 et B = 0 dans sa vue d'ensemble (vue principale du contrôleur). 

Faites glisser 3 UIVIew dans la vue de défilement pour l'utiliser comme vue de contenu avec les contraintes L-0, T = 0, T = 0, B = 0 vers sa vue d'ensemble

  • bien ici son heure pour définir la taille du contenu de la vue de défilement, qui contrôle le défilement horizontalement et verticalement comme suit.

4-pour arrêter le défilement horizontal, faites en sorte que l'affichage du contenu ait la même largeur que scrollview avec contrainte.

5-make hauteur de contenu vue égale hauteur de contrôleur, Ceci est temporaire jusqu'à ce que nous remplissions avec du contenu défilable.

6-ajouter des contrôles dans la vue du contenu jusqu'à la fin.

7 - et le plus important, supprimez la contrainte que vous avez définie au point 5 de la vue de haut contenu et créez une contrainte à partir du contrôle situé en bas de la vue de contenu pour l'aligner en bas. Cela aide à rendre la vue du contenu haute depuis le premier contrôle en haut et en bas jusqu'au dernier contrôle (tout dépend de cette étape). 

8-juste courir et les résultats devraient être comme prévu, sinon s'il vous plaît faites le moi savoir.

J'espère que cela t'aides!

3
IsPha

Grâce à @NadtheVlad, j'ai enfin vu la lumière. Certains autres manipulations m'ont appris que contentView doit simplement être épinglé pour que les vues Haut, Bas et Largeur de scrollView Pas besoin de faire référence à self.view. 

Avec EasyPeasy , ceci est simplement:

scrollView <- Edges()
contentView <- [Top(), Bottom(), Width().like(scrollView)]
0
jazzgil

J'utilise cette implémentation uniquement pour les vues de défilement horizontales/verticales, bien que ce soit dans Objective-C, je vais essayer d'expliquer la logique si quelque chose vous est incertain. 

//Getting iDevice's screen width
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGFloat screenWidth = screenRect.size.width;

//Setting the right content size - only height is being calculated depenging on content.
CGSize contentSize = CGSizeMake(screenWidth, HEIGHT_OF_YOUR_CONTENT);
self.scrollView.contentSize = contentSize;

La largeur de la propriété contentSize de la vue de défilement est maintenant liée à la largeur réelle de l'écran du périphérique. La vue de défilement défilera donc uniquement dans le sens vertical.

0
Richard Topchiy