Comment désactiver le défilement horizontal d'UIScrollView?

92

J'ai un UIViewtremplin semblable à celui de l'iPhone. Je l'ai créé en utilisant un UIScrollViewet UIButtons. Je veux désactiver le défilement horizontal sur ledit scrollview. Je veux seulement un défilement vertical. Comment faire cela?

Rahul Vyas
la source
5
Vous devez changer votre titre: vous demandez horizontal dans la question et vertical dans le titre. Les gens trouvent vos questions plus tard sur les moteurs de recherche, donc ça compte toujours 2 ans plus tard :)
Julien
@RahulVyas L'homme ci-dessus a raison. Changer le titre réduira toute confusion pour les débutants qui arrivent ici via un moteur de recherche (comme moi;)).
SpacyRicochet le
Avoir édité le titre au nom de l'affiche. (Bien qu'il soit actuellement en attente d'examen par les pairs avant que la modification ne soit visible.)
Duncan Babbage

Réponses:

125

Vous devez définir la contentSizepropriété du UIScrollView. Par exemple, si vous avez UIScrollViewune largeur de 320 pixels (la largeur de l'écran), vous pouvez faire ceci:

CGSize scrollableSize = CGSizeMake(320, myScrollableHeight);
[myScrollView setContentSize:scrollableSize];

Le UIScrollViewdéfilera alors uniquement verticalement, car il peut déjà tout afficher horizontalement.

Dave DeLong
la source
6
Salut. Cette solution fonctionne vraiment bien! Merci pour ça. J'ai essayé de régler la largeur statique à 0. Pour moi, cela fonctionne aussi. Je ne sais pas s'il pourrait y avoir des effets secondaires plus tard. Mais si l'on ne connaît pas la taille (c'est-à-dire le code universel pour iPhone et iPad), cela fonctionne très bien!
JackPearse
5
Je pense qu'il vaut mieux faire CGSizeMake (0, myScrollableHeight), donc le défilement horizontal est désactivé même si toutes les sous-vues ne sont pas affichées.
LightNight
NB
Si vous définissez l'
1
Au lieu de passer la largeur en tant que 320 codé en dur, nous pouvons passer comme: CGSize scrollableSize = CGSizeMake (self.scrollview.frame.size.width, myScrollableHeight); [myScrollView setContentSize: scrollableSize];
Mohit kumar le
90

MISE À JOUR: (après que @EranMarom l'ait souligné dans son commentaire)

Vous pouvez arrêter le défilement horizontal ou le défilement vertical dans la ScrollViewDelegateméthode. Voici comment,

Arrête le défilement horizontal:

Si vous souhaitez faire défiler horizontalement, vous devez augmenter la valeur contentOffset.x. Empêcher que s'arrête le défilement de la vue de défilement dans le sens horizontal.

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    sender.contentOffset.x = 0.0
}

Arrête le défilement vertical:

Si vous souhaitez faire défiler verticalement, vous devez augmenter la valeur contentOffset.y. Empêcher que s'arrête le défilement de la vue de défilement dans le sens vertical.

- (void)scrollViewDidScroll:(UIScrollView *)sender {
    sender.contentOffset.y = 0.0
}

Le code ci-dessus empêche les changements dans xet yde a scrollview contentOffsetet cela conduit à arrêter le défilement dans la scrollViewDidScroll:méthode.

Dinesh Raja
la source
1
J'envisage de voter parce que cette réponse n'explique pas que vous venez de donner du code et c'est tout. Une réponse comme ça n'est pas très bonne. Une bonne réponse s'explique, tandis que les développeurs expérimentés peuvent comprendre que les nouveaux développeurs pourraient ne pas comprendre ce qui se passe ici. Pas encore critiqué comme donnant la chance de s'améliorer.
Popeye
13
C'est une sorte de piratage, mais cela a fonctionné quand tout le reste a échoué. Donc +1, mais à n'utiliser qu'en dernier recours.
i_am_jorf
5
J'utilise également cette méthode déléguée, mais je remplace le corps par un one-liner, par exemple: scrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y);pour désactiver le défilement horizontal. Je le trouve plus lisible, il est plus petit et il ne sert à rien de faire le test pour zéro car il n'y a pratiquement pas de surcharge avec du code qui s'exécute rarement (c'est-à-dire quelques dizaines de fois par seconde max).
Echelon le
parce que vous changez le contenu Offset après "didscroll", pas comme avant "willscroll", et c'est une solution marteau, mais je n'ai pas moi-même voté contre, parce que 18 votes pour et la réponse est 75, donc ce n'est pas digne de voter
LolaRun
2
Encore plus simple, utilisez scrollView.contentOffset.y = 0.0pour arrêter le défilement vertical et scrollView.contentOffset.x = 0.0pour arrêter le défilement horizontal, dans la scrollViewDidScroll()fonction délégué. Cependant, je pense que s'assurer que l' scrollView.contentSizeégalité scrollView.frame.sizeest égale à est une meilleure solution (correcte). Voir la réponse @danbeaulieu.
emem
11

depuis l'utilisation d'iOS7

self.automaticallyAdjustsScrollViewInsets = NO;

// et créez votre défilement de page avec 3 pages

    self.pageView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, self.view.frame.size.height)];
    [self.pageView setContentSize:CGSizeMake(self.view.frame.size.width*3, self.view.frame.size.height)];
    [self.pageView setShowsVerticalScrollIndicator:NO];
    [self.pageView setPagingEnabled:YES];
    [self.view addSubview:self.pageView];
Mirko Brunner
la source
Je ne pense pas que cela désactivera le comportement de défilement d'un scrollview. Est-ce que c'est ??
Dinesh Raja
self.collectionView.pagingEnabled = YES;m'a aidé à résoudre le problème de défilement fluide (pas de glissement). Le problème était dans method scrollViewWillEndDragging:- targetContentOffset était le même que scrollView.contentOffset et la logique de détection de page ne fonctionne pas correctement.
sig
11

Solution rapide

Créez deux points de vente, un pour votre vue et un pour votre vue de défilement:

@IBOutlet weak var myView: UIView!
@IBOutlet weak var scrollView: UIScrollView!

Ensuite, dans votre viewDidLayoutSubviews, vous pouvez ajouter le code suivant:

let scrollSize = CGSize(width: myView.frame.size.width, 
                        height: myView.frame.size.height)
scrollView.contentSize = scrollSize

Ce que nous avons fait, c'est collecter la hauteur et la largeur de la vue et définir la taille du contenu scrollViews en conséquence. Cela empêchera votre scrollview de défiler horizontalement.


Plus de pensées:

CGSizeMake prend une largeur et une hauteur en utilisant CGFloats. Vous devrez peut-être utiliser votre hauteur existante UIScrollViews pour le deuxième paramètre. Ce qui ressemblerait à ceci:

let scrollSize = CGSize(width: myView.frame.size.width, 
                        height: scrollView.contentSize.height)
Dan Beaulieu
la source
Et si vous ne connaissez pas la hauteur ou la largeur (appareil universel)? @danbeaulieu
Lukesivi
@lukesIvi "myView.frame.width" extrait dynamiquement la largeur de l'IBOutlet "myView".
Dan Beaulieu
4

Dans mon cas, avec Swift 4.2, vous pouvez utiliser:

Désactiver le défilement vertical:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.y = 0.0
}

Désactiver le défilement horizontal:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.x = 0.0
}
Ricardo
la source
3

Vous pouvez sélectionner la vue, puis Attributes Inspectordécocher User Interaction Enabled.

Codeur221
la source
3

Dans mon cas, la largeur du contentView était supérieure à la largeur de UIScrollView et c'était la raison du défilement horizontal indésirable. Je l'ai résolu en définissant la largeur de contentView égale à la largeur de UIScrollView.

J'espère que ça aide quelqu'un

Gulfam Khan
la source
@Nostradamus heureux d'aider
Gulfam Khan
0

J'ai eu le tableview contentInset défini dans viewDidLoad (comme ci-dessous) ce qui cause le défilement horizontal

self.tableView.contentInset = UIEdgeInsetsMake(0, 30, 0, 0);

Vérifiez s'il y a un contenu tableviewInset défini pour différentes raisons et désactivez-le

Naishta
la source
0

J'ai eu du mal avec cela pendant un certain temps en essayant sans succès les différentes suggestions de ce sujet et d'autres fils.

Cependant, dans un autre thread (je ne sais pas où), quelqu'un a suggéré que l'utilisation d'une contrainte négative sur UIScrollView fonctionnait pour lui.

J'ai donc essayé différentes combinaisons de contraintes avec des résultats incohérents. Ce qui a finalement fonctionné pour moi a été d'ajouter des contraintes de début et de fin de -32 à la vue de défilement et d'ajouter une vue de texte (invisible) avec une largeur de 320 (et centrée).

PatriciaW
la source
0

Essaye ça:

CGSize scrollSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, scrollHeight);
[scrollView setContentSize: scrollSize];
Torongo
la source
0

Désactivez le défilement horizontal en remplaçant la contentOffsetpropriété dans la sous-classe.

override var contentOffset: CGPoint {
  get {
    return super.contentOffset
  }
  set {
    super.contentOffset = CGPoint(x: 0, y: newValue.y)
  }
}
iWheelBuy
la source
0

Introduit dans iOS 11 est une nouvelle propriété sur UIScrollView

var contentLayoutGuide: UILayoutGuide

La documentation indique que vous:

Utilisez ce guide de mise en page lorsque vous souhaitez créer des contraintes de mise en page automatique liées à la zone de contenu d'une vue de défilement.

En plus de toute autre contrainte de mise en page automatique que vous pourriez ajouter, vous souhaiterez contraindre widthAnchorles UIScrollView's contentLayoutGuideà avoir la même taille que le "cadre". Vous pouvez utiliser le frameLayoutGuide(également introduit dans iOS 11) ou n'importe quelle largeur externe (telle que la vôtre superView.)

exemple:

NSLayoutConstraint.activate([
  scrollView.contentLayoutGuide.widthAnchor.constraint(equalTo: self.widthAnchor)
])

Documentation: https://developer.apple.com/documentation/uikit/uiscrollview/2865870-contentlayoutguide

JMFR
la source
-1

Une fois que je l'ai fait en remplaçant UIScrollView par un UITableView avec seulement 1 cellule, cela a bien fonctionné.

Hola Soy Edu Feliz Navidad
la source
1
Désolé, cela ne répond pas à la question.
David
-1

Utilisez cette seule ligne.

self.automaticallyAdjustsScrollViewInsets = NO;

Karthickkck
la source