web-dev-qa-db-fra.com

UIScrollView ne défile pas

J'ai une UIScrollView qui contient plusieurs UIImageViews, UILabels, etc ... les étiquettes sont beaucoup plus longues que la UIScrollView, mais lorsque je lance l'application, je ne peux pas cliquer et faire défiler vers le bas ...

Pourquoi cela pourrait-il être?

Merci

116
Mark

Il est toujours bon d'afficher un extrait de code fonctionnel complet:

// in viewDidLoad (if using Autolayout check note below):

UIScrollView *myScrollView;
UIView *contentView;
// scrollview won't scroll unless content size explicitly set

[myScrollView addSubview:contentView];//if the contentView is not already inside your scrollview in your xib/StoryBoard doc

myScrollView.contentSize = contentView.frame.size; //sets ScrollView content size

Swift 4.0

let myScrollView
let contentView

// scrollview won't scroll unless content size explicitly set

myScrollView.addSubview(contentView)//if the contentView is not already inside your scrollview in your xib/StoryBoard doc

myScrollView.contentSize = contentView.frame.size //sets ScrollView content size

Je n'ai pas trouvé de moyen de définir contentSize dans IB (à partir de Xcode 5.0).

Remarque: Si vous utilisez Autolayout, le meilleur endroit pour insérer ce code se trouve dans la méthode -(void)viewDidLayoutSubviews.

158
Bogatyr

Si vous ne parvenez pas à faire défiler la vue même après avoir correctement défini contentSize, assurez-vous que décochez "Utiliser la mise en page automatique" dans Interface Builder -> Inspecteur de fichier.

120
user1539652

Vous devez définir la propriété contentSize de la vue de défilement pour que celle-ci défile correctement.

Si vous utilisez autolayout, vous devez définir contentSize dans viewDidLayoutSubviews pour pouvoir l'appliquer à la fin de la procédure.

Le code pourrait ressembler à ceci:

-(void)viewDidLayoutSubviews
{
    // The scrollview needs to know the content size for it to work correctly
    self.scrollView.contentSize = CGSizeMake(
        self.scrollContent.frame.size.width,
        self.scrollContent.frame.size.height + 300
    );
}
64
Chris Vasselli

La réponse ci-dessus est correcte - pour que le défilement se produise, il est nécessaire de définir la taille du contenu. 

Si vous utilisez le générateur d'interface, une méthode simple consiste à utiliser des attributs d'exécution définis par l'utilisateur. Par exemple: 

enter image description here

45
Jasper Blues

Essayez de redimensionner la taille du contenu à des nombres énormes. Je ne comprenais pas pourquoi ma vue de défilement ne défilait pas alors que sa taille de contenu semblait être supérieure à la taille du contrôle. J'ai découvert que si la taille du contenu est plus petite que nécessaire, cela ne fonctionne pas aussi. 

self.scrollView.contentSize = CGSizeMake(2000, 2000);

Au lieu de 2000, vous pouvez mettre vos propres grands chiffres. Et si cela fonctionne, cela signifie que la taille de votre contenu n'est pas assez grande lorsque vous redimensionnez. 

Le délégué n'est pas nécessaire pour que l'affichage par défilement fonctionne. 

35
wzbozon

Assurez-vous que la propriété contentSize de la vue de défilement est définie sur la taille correcte (c'est-à-dire, une taille suffisante pour englober tout votre contenu.)

13
Ben Gottlieb

Décocher 'Utiliser Autolayout' a fait l'affaire pour moi. 

Environnement: XCode 5.0.2 Storyboards Ios7 

7
Gaurav Kumkar

Dans mon cas, je devais définir delaysContentTouches sur true car les objets à l'intérieur de scrollView capturaient tous les événements tactiles et se traitaient eux-mêmes plutôt que de laisser le scrollView lui-même le gérer.

4
devios1

si vous recevez un message (IOS8/Swift) indiquant que viewDidLayoutSubviews n'existe pas, utilisez plutôt le code suivant

override func viewDidAppear(animated: Bool)

Cela a résolu le problème pour moi

3
Jason G

Définissez la propriété contentSize de UIScrollview dans la méthode ViewDidLayoutSubviews. Quelque chose comme ça 

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    scrollView.contentSize = CGSizeMake(view.frame.size.width, view.frame.size.height)
}
3
Vinayak Parmar

Un petit ajout, tous les précédents sont les raisons pour lesquelles votre vue de défilement peut ne pas défiler, mais parfois sans raison, cela pourrait être la raison spécialement lorsque scrollview est ajouté par le code et non par IB, vous avez peut-être ajouté vos sous-vues à la vue parent et non à le scrollview cela fait que la sous-vue ne défile pas

et conservez la taille du contenu définie et supérieure à celle du cadre de vue parent (duhh !!)

3
carelesslyChoosy

L'idée de faire défiler la vue en défilant parce que vous définissez une taille de contenu inférieure à la taille de la vue de défilement, ce qui est faux tout en faisant défiler.

La même idée avec le zoom, vous définissez la valeur minimale et maximale du zoom qui sera appliquée par l’action du zoom.

bienvenue :) 

3
Abo3atef

Bien souvent, le code est correct si vous avez suivi un tutoriel, mais ce que beaucoup de débutants ne savent pas, c’est que scrollView estPASva faire défiler normalement le simulateur. Il est supposé faire défiler uniquement lorsque vous appuyez sur les touches mousepad et simultanément. Beaucoup d'utilisateurs expérimentés XCode/Swift/Obj-C sont habitués à le faire et ne savent pas comment les débutants pourraient l'ignorer. Ciao :-)

@IBOutlet weak var scrollView: UIScrollView!
override func viewDidLoad() {
    super.viewDidLoad()
    view.addSubview(scrollView)
    // Do any additional setup after the view
}

override func viewWillLayoutSubviews(){
    super.viewWillLayoutSubviews()
    scrollView.contentSize = CGSize(width: 375, height: 800)
}

Ce code fonctionnera parfaitement tant que vous ferez ce que j'ai dit plus haut

2
flo527

Quelque chose qui n'a pas été mentionné auparavant!

Assurez-vous que votre prise a été correctement connectée au scrollView! Il devrait y avoir un cercle rempli, mais même si vous en avez déjà un, scrollView n'est peut-être pas connecté. Survolez le cercle et voyez si la vue de défilement est mise en évidence! (C'était un cas pour moi)

//Connect below well to the scrollView in the storyBoard
@property (weak, nonatomic) IBOutlet UIScrollView *scrollView;
2
coolcool1994

Si votre scrollView est une sous-vue d'une containerView d'un certain type, assurez-vous que votre scrollView se trouve dans le cadre ou les limites de la containerView. J'avais containerView.clipsToBounds = NO qui me permettait toujours de voir scrollView, mais comme scrollView n'était pas dans les limites de containerView, il ne détecterait pas les événements tactiles.

Par exemple:

containerView.frame = CGRectMake(0, 0, 200, 200);
scrollView.frame = CGRectMake(0, 200, 200, 200);
[containerView addSubview:scrollView];
scrollView.userInteractionEnabled = YES;

Vous pourrez voir le scrollView mais il ne recevra pas les interactions de l'utilisateur.

1
Chase Roberts

Si aucune autre solution ne fonctionne pour vous, vérifiez que votre vue défilement est bien une UIScrollView dans Interface Builder.

Au cours des derniers jours, ma UIScrollView a spontanément changé de type en UIView, même si sa classe a déclaré UIScrollView dans l'inspecteur. J'utilise Xcode 5.1 (5B130a).

Vous pouvez soit créer une nouvelle vue de défilement et copier les mesures, les paramètres et les contraintes de l'ancienne vue, soit modifier manuellement la vue en une variable UIScrollView dans le fichier xib. J'ai fait une comparaison et trouvé les différences suivantes:

Original:

<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" directionalLockEnabled="YES" bounces="NO" pagingEnabled="YES" showsHorizontalScrollIndicator="NO" showsVerticalScrollIndicator="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Wsk-WB-LMH">
...
</scrollView>

Après que le type ait changé spontanément:

<view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" customClass="UIScrollView" id="qRn-TP-cXd">
...
</view>

J'ai donc remplacé la ligne <view> par ma ligne <scrollView> d'origine.

J'ai également remplacé la balise de fermeture de la vue </view> par </scrollView>.

Assurez-vous de garder l'ID identique à celui de la vue actuelle, dans ce cas: id = "qRn-TP-cXd".

J'ai également dû vider le xib du cache de Xcode en supprimant les données dérivées de l'application:

  • Xcode->Window->Organizer->Projects, choisissez votre projet, sur la ligne de données dérivées, cliquez sur Supprimer ...

Ou si vous utilisez un appareil:

  • Xcode->Window->Organizer->Device, choisissez votre appareil-> Applications, choisissez votre application, cliquez sur (-)

Maintenant, nettoyez le projet et supprimez l'application du simulateur/appareil:

  • Xcode->Product->Clean
  • iOS Simulator/device->press et maintenez le app->click le (X) pour le supprimer

Vous devriez alors pouvoir créer et exécuter votre application et avoir à nouveau la fonctionnalité de défilement.

P.S. Je n'ai pas eu à définir la taille du contenu de la vue de défilement dans viewDidLayoutSubviews ou à désactiver la mise en page automatique, mais YMMV.

1
Zack Morris

ajouter le code suivant dans viewDidLayoutSubviews a fonctionné pour moi avec Autolayout. Après avoir essayé toutes les réponses:

- (void)viewDidLayoutSubviews
{
    self.activationScrollView.contentSize = CGSizeMake(IPHONE_SCREEN_WIDTH, 620);

}

//set the height of content size as required
1
Savvy iPhone

Ajouter la UIScrollViewDelegate et l'ajout du code suivant à la méthode viewDidAppear l'a corrigé.

@interface testScrollViewController () <UIScrollViewDelegate>

-(void)viewDidAppear:(BOOL)animated {
    self.scrollView.delegate = self;
    self.scrollView.scrollEnabled = YES;
    self.scrollView.contentSize = CGSizeMake(375, 800);
}
1
Trianna Brannon

J'ai constaté qu'avec ce problème de mise en forme automatique ... si je faisais simplement que ViewController utilise UIView au lieu de UIScrollView pour la classe ... ajoutez simplement UIScrollView moi-même ... que cela fonctionne.

0
Brian Rice

encore un cas amusant:

scrollview.superview.userInteractionEnabled doit être true

J'ai perdu plus de 2 heures à chercher ce que le parent est UIImageView, qui a naturellement userInteractionEnabled == false

0
Anton Tropashko

Après avoir échoué avec les réponses fournies dans ce fil, je suis tombé sur cet article avec la solution.

Il y a deux choses pas intuitives dans la configuration de scrollview avec autolayout:

  1. Les contraintes que vous définissez comme marge entre contentview et scrollview n'influencent pas la taille de la contentview. Ce sont vraiment des marges. Et pour que cela fonctionne, le contentview doit avoir une taille fixe.
  2. Le truc à la taille fixe est que vous pouvez définir la largeur de la contentview égale à celle du parent de la scrollview. Il suffit de sélectionner les deux vues dans l’arbre de gauche et d’ajouter la contrainte d’égales largeurs.

C’est l’essentiel de cet article. Pour une explication complète, y compris des illustrations, consultez-la.

0
H. de Jonge

Mon problème a été résolu par:

  1. réglage de contentSize sur le scrollView sur une hauteur importante
  2. MAIS je devais aussi fixer les contraintes du haut et/ou du bas sur les vues dans scrollView, ce qui signifiait que les indicateurs de défilement étaient affichés à l'écran mais que le contenu ne défilait pas.

Une fois que j'ai supprimé les contraintes du haut et/ou du bas liées à la zone sécurisée et/ou à la vue d'ensemble, les vues à l'intérieur du scrollView pouvaient défiler à nouveau et ne restaient pas figées en haut de l'écran!

J'espère que cela empêchera quelqu'un d'autre de passer des heures douloureuses dans ce problème particulier.

0
Henry Heleine

J'ai eu le même problème dans IB.

Après avoir défini le début, la fin, le haut et le bas du scrollView sur son superView. J'ai apporté les modifications suivantes pour rendre le conteneurView scrollable, ce qui a fonctionné.

Pour que scrollView défile uniquement dans le sens horizontal, définissez la contrainte avec le centre de scrollViewY = le centreY de ContainerView

et pour le faire défiler verticalement, faites le centre de scrollViewX = le centreX de ContainerView 

0
Nandu

Je l'ai fait fonctionner à mon premier essai. Avec la mise en page automatique et tout, pas de code supplémentaire. Ensuite, une vue de collection s'est transformée en banane, avec un crash au moment de l'exécution. Je ne pouvais pas trouver ce qui n'allait pas, alors je l'ai effacée et recréée (j'utilise Xcode 10 Beta 4. C'était comme un bug) et le défilement a disparu. La vue Collection a de nouveau fonctionné!

Plusieurs heures plus tard… c'est ce qui me l'a réglé. J'ai eu la mise en page suivante:

UIView

  • Zone protégée
  • Faites défiler la vue
    • Vue du contenu

Tout est dans les contraintes. La zone de sécurité est automatiquement définie par le système. Dans le pire des cas, supprimez toutes les contraintes pour les vues de défilement et de contenu et non demandez à IB de les réinitialiser/de les créer pour vous. Faites-les manuellement, ça marche.

  • Pour la vue de défilement, j’ai fait: Aligner le fin/le haut sur la zone de sécurité. Égale largeur/hauteur à la zone de sécurité.
  • Pour l’affichage du contenu, j’ai fait: Aligner le suivi, l’avant/le haut/le bas sur l’aperçu (la vue par défilement)

le concept consiste essentiellement à avoir la vue Contenu adaptée à Scrollview, qui est adaptée à la zone sécurisée. 

Mais en tant que tel cela n'a pas fonctionné. La vue du contenu a manqué la hauteur. J'ai essayé tout ce que je pouvais et le seul qui ait fait le tour est une hauteur de la vue du contenu créée en faisant glisser la vue du contenu en maintenant la touche Contrôle enfoncée .. vers lui-même. Cela définissait une hauteur fixe, dont la valeur a été calculée à partir de la taille du contrôleur de vue (définie comme forme libre, plus longue que l'affichage réel, pour contenir tous mes sous-vues) et enfin cela a fonctionné à nouveau!

0
Michele Dall'Agata