Wie deaktiviere ich das horizontale Scrollen von UIScrollView?


92

Ich habe ein UIViewähnliches iPhone-Sprungbrett. Ich habe es mit einem UIScrollViewund erstellt UIButtons. Ich möchte das horizontale Scrollen in dieser Bildlaufansicht deaktivieren. Ich möchte nur vertikales Scrollen. Wie schaffe ich das?


5
Sie sollten Ihren Titel ändern: Sie fragen in der Frage nach horizontal und im Titel nach vertikal. Die Leute finden Ihre Fragen später in Suchmaschinen, also ist es auch 2 Jahre später noch wichtig :)
Julien

@ RahulVyas Der Mann oben hat einen Punkt. Das Ändern des Titels verringert die Verwirrung für Anfänger, die über eine Suchmaschine hierher kommen (wie ich;)).
SpacyRicochet

Habe den Titel im Namen des Posters bearbeitet. (Obwohl es derzeit auf Peer Review wartet, bevor die Bearbeitung sichtbar wird.)
Duncan Babbage

Antworten:


125

Sie müssen die contentSizeEigenschaft von festlegen UIScrollView. Wenn Sie UIScrollViewbeispielsweise 320 Pixel breit sind (die Breite des Bildschirms), können Sie Folgendes tun:

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

Der UIScrollViewwird dann nur vertikal scrollen, da er bereits alles horizontal anzeigen kann.


6
Hallo. Diese Lösung funktioniert wirklich gut! Dank dafür. Ich habe versucht, die statische Breite auf 0 zu setzen. Bei mir funktioniert das auch. Ich weiß nicht, ob es später einige Nebenwirkungen geben könnte. Aber wenn man die Größe nicht kennt (dh Universalcode für iPhone und iPad), funktioniert das großartig!
JackPearse

5
Ich denke, es ist besser, CGSizeMake (0, myScrollableHeight) auszuführen, sodass das horizontale Scrollen deaktiviert ist, auch wenn nicht alle Unteransichten angezeigt werden.
LightNight

NB Wenn Sie bei Verwendung von Paging eine der Dimensionen auf 0 setzen, wird VoiceOver die Seitenzahl unabhängig vom korrekten Wert als "Seite 1 von 1" ankündigen
Josef

1
Anstatt die Breite als 320 fest codiert zu übergeben, können wir Folgendes übergeben: CGSize scrollableSize = CGSizeMake (self.scrollview.frame.size.width, myScrollableHeight); [myScrollView setContentSize: scrollableSize];
Mohit Kumar

90

AKTUALISIERT: (Nachdem @EranMarom auf seinen Kommentar hingewiesen hat)

Sie können das horizontale oder vertikale Scrollen in der ScrollViewDelegateMethode stoppen . Hier ist es wie,

Stoppt das horizontale Scrollen:

Wenn Sie horizontal scrollen möchten, müssen Sie contentOffset.x erhöhen. Wenn Sie dies verhindern, wird der Bildlauf in horizontaler Richtung gestoppt.

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

Stoppt das vertikale Scrollen:

Wenn Sie vertikal scrollen möchten, müssen Sie contentOffset.y erhöhen. Wenn Sie dies verhindern, wird der Bildlauf in vertikaler Richtung gestoppt.

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

Der obige Code verhindert die Änderungen in xund yvon a scrollview contentOffsetund führt dazu, dass das Scrollen in der scrollViewDidScroll:Methode gestoppt wird.


1
Ich denke über ein Downvoting nach, weil diese Antwort nicht erklärt, dass Sie selbst gerade Code gegeben haben und das war's. Antworten wie diese sind nicht sehr gut. Gute Antworten erklären sich selbst, während erfahrene Entwickler möglicherweise verstehen, dass neuere Entwickler möglicherweise nicht verstehen, was hier vor sich geht. Noch nicht herabgestuft, um die Chance zu geben, sich zu verbessern.
Popeye

13
Dies ist eine Art Hack, aber es hat funktioniert, als alles andere fehlgeschlagen ist. Also +1, aber nur als letztes Mittel verwenden.
i_am_jorf

5
Ich verwende auch diese Delegatenmethode, ersetze aber den Körper durch einen Einzeiler, z. B.: Um das scrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y);horizontale Scrollen zu deaktivieren. Ich finde es besser lesbar, es ist kleiner und es macht keinen Sinn, den Test für Null durchzuführen, da es praktisch keinen Overhead mit Code gibt, der dies selten ausführt (dh maximal einige zehn Mal pro Sekunde).
Echelon

weil du das contentOffset nach "didscroll" änderst, nicht wie vor 'willscroll', und dies ist eine Hammerlösung, aber ich selbst habe nicht abgelehnt, weil 18 positive Stimmen und die Antwort 75 sind, also ist es nicht wert, herabgestimmt zu werden
LolaRun

2
Noch einfacher ist es , in der Delegate-Funktion das scrollView.contentOffset.y = 0.0vertikale Scrollen und scrollView.contentOffset.x = 0.0das horizontale Scrollen zu stoppen scrollViewDidScroll(). Ich glaube jedoch, dass es eine bessere (richtige) Lösung ist, sicherzustellen, dass das scrollView.contentSizeGleiche dem entspricht scrollView.frame.size. Siehe @ danbeaulieu Antwort.
Emem

11

seit iOS7 verwenden

self.automaticallyAdjustsScrollViewInsets = NO;

// und erstelle deinen Seiten-Scroller mit 3 Seiten

    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];

Ich glaube nicht, dass dies das Bildlaufverhalten einer Bildlaufansicht deaktivieren wird. Ist es??
Dinesh Raja

self.collectionView.pagingEnabled = YES;half mir, das Problem mit dem reibungslosen Scrollen (nicht Ziehen) zu lösen. Das Problem lag in der Methode scrollViewWillEndDragging:- targetContentOffset war dasselbe wie scrollView.contentOffset und die Seitenerkennungslogik funktioniert nicht richtig.
Sig

11

Schnelle Lösung

Erstellen Sie zwei Steckdosen, eine für Ihre Ansicht und eine für Ihre Bildlaufansicht:

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

Dann können Sie in Ihren viewDidLayoutSubviews den folgenden Code hinzufügen:

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

Wir haben die Höhe und Breite der Ansicht erfasst und die Größe des scrollViews-Inhalts entsprechend festgelegt. Dadurch wird verhindert, dass Ihre Bildlaufansicht horizontal gescrollt wird.


Weitere Gedanken:

CGSizeMake nimmt mit CGFloats eine Breite und Höhe an. Möglicherweise müssen Sie die vorhandene Höhe Ihrer UIScrollViews für den zweiten Parameter verwenden. Welches würde so aussehen:

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

Was ist, wenn Sie weder die Höhe noch die Breite kennen (Universalgerät)? @ Danbeaulieu
Lukesivi

@lukesIvi "myView.frame.width" zieht dynamisch die Breite aus dem IBOutlet "myView".
Dan Beaulieu

4

In meinem Fall können Sie mit Swift 4.2 Folgendes verwenden:

Vertikales Scrollen deaktivieren:

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

Horizontalen Bildlauf deaktivieren:

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

3

Sie können die Ansicht auswählen und dann Attributes Inspectordeaktivieren User Interaction Enabled.


3

In meinem Fall war die Breite von contentView größer als die Breite von UIScrollView und dies war der Grund für unerwünschtes horizontales Scrollen. Ich habe es gelöst, indem ich die Breite von contentView gleich der Breite von UIScrollView gesetzt habe.

Hoffe es hilft jemandem


@Nostradamus gerne helfen
Gulfam Khan

0

Ich hatte die Tabellenansicht contentInset in viewDidLoad (wie unten) so eingestellt, dass sie das horizontale Scrollen verursacht

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

Überprüfen Sie, ob aus verschiedenen Gründen eine Tabellenansicht für contentInset festgelegt ist, und deaktivieren Sie diese


0

Ich hatte einige Zeit damit zu kämpfen und versuchte erfolglos, die verschiedenen Vorschläge in diesem und anderen Threads zu machen.

In einem anderen Thread (nicht sicher, wo) schlug jemand vor, dass die Verwendung einer negativen Einschränkung für UIScrollView für ihn funktioniert.

Also habe ich verschiedene Kombinationen von Einschränkungen mit inkonsistenten Ergebnissen ausprobiert. Was schließlich für mich funktioniert hat, war, der Bildlaufansicht führende und nachfolgende Einschränkungen von -32 hinzuzufügen und eine (unsichtbare) Textansicht mit einer Breite von 320 (und zentriert) hinzuzufügen.


0

Versuche dies:

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

0

Deaktivieren Sie das horizontale Scrollen, indem Sie die contentOffsetEigenschaft in der Unterklasse überschreiben .

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

0

In iOS 11 wurde eine neue Eigenschaft eingeführt UIScrollView

var contentLayoutGuide: UILayoutGuide

Die Dokumentation besagt, dass Sie:

Verwenden Sie diese Layoutanleitung, wenn Sie Einschränkungen für das automatische Layout für den Inhaltsbereich einer Bildlaufansicht erstellen möchten.

Zusammen mit anderen Autolayout Einschränkungen , dass Sie Sie wollen vielleicht das Hinzufügen der beschränken widthAnchorder UIScrollView‚s contentLayoutGuidedie gleiche Größe sein , wie der‚Rahmen‘. Sie können die frameLayoutGuide(auch in iOS 11 eingeführte) oder eine beliebige externe Breite (z. B. Ihre) verwendensuperView ) verwenden.

Beispiel:

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

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


-1

Nachdem ich das UIScrollView durch ein UITableView mit nur 1 Zelle ersetzt hatte, funktionierte es einwandfrei.


1
Entschuldigung, das beantwortet die Frage nicht.
David

-1

Verwenden Sie diese einzelne Zeile.

self.automaticallyAdjustsScrollViewInsets = NO;

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.