Désactivation du défilement vertical dans UIScrollView

Réponses:

121

Essayez de définir la hauteur de contentSize sur la hauteur de scrollView. Ensuite, le défilement vertical devrait être désactivé car il n'y aurait rien à faire défiler verticalement.

scrollView.contentSize = CGSizeMake(scrollView.contentSize.width,scrollView.frame.size.height);
pt2ph8
la source
Vous venez de me faire gagner beaucoup de temps en déboguant ce problème étrange. Merci!
jpm
2
@fabb comment sait-on quand le cadre est changé?
Sam
137

depuis iOS7:

d'abord: la largeur de la taille du contenu doit être égale à la largeur de votre scrollview

second: dans votre initWithNibName:

self.automaticallyAdjustsScrollViewInsets = NO;

C'est ça.

Mirko Brunner
la source
Magnifique solution. A travaillé comme un charme. Cela affectera-t-il la taille du reste des vues dans mon ViewController? (Boutons, étiquettes ..) Je veux dire, "self" est un UIViewController dans mon cas
voghDev
@voghDev non cela n'a aucun effet sur les sous-vues de votre scrollview.
Mirko Brunner
Amazing a ajouté cela à la méthode viewdidload sur mes contrôleurs de vue qui rencontraient des problèmes.
StackRunner
si vous utilisez navigationController et que votre scrollview est derrière le titre de navigationBar comme le mien, utilisez la méthode viewDidLoad. Cela résout.
EFE
1
Vous pouvez obtenir la même chose dans les paramètres du storyboard directement sans aucune ligne de code. Sélectionnez simplement le contrôleur de vue de défilement et décochez la case "Ajuster les encarts de vue de défilement" dans l'inspecteur d'attributs.
Morpheus78
49

oui, la réponse de pt2ph8 est juste,

mais si, pour une raison étrange, votre contentSize doit être supérieur à UIScrollView, vous pouvez désactiver le défilement vertical implémentant la méthode de protocole UIScrollView

 -(void)scrollViewDidScroll:(UIScrollView *)aScrollView;

ajoutez simplement ceci dans votre UIViewController

float oldY; // here or better in .h interface

- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
{
    [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x, oldY)];
    // or if you are sure you wanna it always on top:
    // [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x, 0)];
}

c'est juste la méthode appelée lorsque l'utilisateur fait défiler votre UIScrollView, et ce faisant, vous forcez son contenu à avoir toujours le même .y

meronix
la source
6
Dieu! Veuillez NE PAS déclarer la variable oldY dans le fichier .m comme float oldY;reportez-vous au code ci-dessus. C'est un symbole de variable de style C pour par application, la variable DOIT être déclarée comme un membre d'instance de la classe de contrôleur.
Itachi
21

Inclure la méthode suivante

-(void)viewDidLayoutSubviews{
    self.automaticallyAdjustsScrollViewInsets = NO;
}

et définissez la largeur de la taille du contenu de la vue de défilement égale à la largeur de la vue de défilement.

Febin P
la source
1
Cela peut également être fait dans Storyboard en sélectionnant le contrôleur de vue et en décochant la propriété là
justColbs
1
Je n'aime pas cela car il le définit pour toutes les vues de défilement ... Je souhaite que vous puissiez être spécifique à une vue de défilement sur le diagramme sans créer une nouvelle classe ScrollView, etc.
visc
20

Vous devez passer 0 dans la taille du contenu pour désactiver la direction souhaitée.

Pour désactiver le défilement vertical

scrollView.contentSize = CGSizeMake(scrollView.contentSize.width,0);

Pour désactiver le défilement horizontal

scrollView.contentSize = CGSizeMake(0,scrollView.contentSize.height);
Mani
la source
1
Cela définira le contentSize de la vue à 0 sur l'axe que vous définissez. ContentSize fait référence à la taille du contenu, nous voulons donc passer dans la hauteur de l'écran pour désactiver le défilement vertical au-delà de ce cadre. la solution marquée comme correcte est correcte.
système
Cela a bien fonctionné pour moi. définir la hauteur comme hauteur de contentSize me faisait toujours défiler verticalement.
KoreanXcodeWorker
1
Cela n'a pas fonctionné pour moi. Également essayé self.automaticallyAdjustsScrollViewInsets
StackRunner
Ça y est ...! Le réglage à la hauteur de la vue de défilement n'a pas fonctionné pour moi, mais cela a fonctionné
Echizzle
18

J'ai mis à jour la taille du contenu pour désactiver le défilement vertical, et la possibilité de faire défiler est restée. Ensuite, j'ai compris que je devais également désactiver le rebond vertical, pour désactiver complètement le défilement.

Peut-être qu'il y a aussi des gens avec ce problème.

Bolonn
la source
Tu m'as sauvé. Mon contenu La taille et le cadre étaient les mêmes et je n'ai pas pu comprendre ce qui n'allait pas toute ma vie. Merci beaucoup !!
yuf
2
Votre réponse est pourquoi j'aime stackoverflow! :-) Sainte fumée ... cela m'a rendu fou! Tu as raison. C'est l'effet de rebond. Je veux l'effet de rebond, mais pas quand il n'est pas nécessaire de faire défiler, donc je chercherai à désactiver / réactiver cet effet maintenant dans le code en fonction de la nécessité ou non de faire défiler.
Erik van der Neut
2
D'accord, très facile d'activer / désactiver les rebonds sur un UIScrollView au moment de l'exécution. Dans mon cas, je ne me soucie que de la hauteur du contenu du défilement et cela a fait l'affaire: self.scrollView.bounces = (BOOL) (self.scrollView.contentSize.height> self.scrollView.frame.size.height);
Erik van der Neut
12
- (void)scrollViewDidScroll:(UIScrollView *)aScrollView
{
    [aScrollView setContentOffset: CGPointMake(aScrollView.contentOffset.x,0)];

}

vous devez avoir confirmé à UIScrollViewDelegate

aScrollView.delegate = self;

la source
4

Réglez simplement le y pour qu'il soit toujours au top. Besoin de se conformer à UIScrollViewDelegate

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

Cela conservera l'effet de décélération / accélération du défilement.

manuelsantos
la source
4

Sur iOS 11, n'oubliez pas d'ajouter ce qui suit, si vous souhaitez créer une vue de défilement qui colle aux limites de l'écran plutôt qu'à une zone de sécurité:

if (@available(iOS 11.0, *)) {
    [self.scrollView setContentInsetAdjustmentBehavior:UIScrollViewContentInsetAdjustmentNever];
}
Michael
la source
1
après tout. merci mille fois monsieur! tu as sauvé ma journée
ha100
0

Depuis iOS11, on peut utiliser la propriété suivante

let frameLayoutGuide: UILayoutGuide

Si vous définissez des contraintes pour frameLayoutGuide.topAnchor et frameLayoutGuide.bottomAnchor sur les mêmes ancres d'une sous- vue de votre scrollView, le défilement vertical sera désactivé et la hauteur de la scrollView sera égale à la hauteur de sa sous-vue.

malex
la source
0

La solution la plus évidente est d'interdire les changements de coordonnées y dans votre sous-classe.

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

C'est la seule solution appropriée dans les situations où:

  1. Vous n'êtes pas autorisé ou ne souhaitez tout simplement pas utiliser de délégué.
  2. La hauteur de votre contenu est supérieure à la hauteur du conteneur
iWheelBuy
la source
0

Beaucoup de réponses incluent la mise contentOffsetà 0. J'ai eu un cas dans lequel je voulais que la vue à l'intérieur de scrollView soit centrée. Cela a fait le travail pour moi:

public func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.y = -scrollView.contentInset.top
}
regina_fallangi
la source