Jak wyłączyć przewijanie w poziomie UIScrollView?

92

Mam UIViewpodobny do iPhone'a Springboard. Stworzyłem go za pomocą UIScrollViewi UIButtons. Chcę wyłączyć przewijanie w poziomie we wspomnianym widoku przewijania. Chcę tylko przewijania w pionie. Jak to osiągnąć?

Rahul Vyas
źródło
5
Powinieneś zmienić swój tytuł: pytasz o poziom w pytaniu i pion w tytule. Ludzie znajdują Twoje pytania później w wyszukiwarkach, więc 2 lata później ma to znaczenie :)
Julien
@RahulVyas Mężczyzna powyżej ma rację. Zmiana tytułu zmniejszy wszelkie zamieszanie u początkujących, którzy trafiają tutaj przez wyszukiwarkę (np. Ja;)).
SpacyRicochet
Zredagowałem tytuł w imieniu autora. (Chociaż obecnie oczekuje na wzajemną recenzję, zanim edycja będzie widoczna.)
Duncan Babbage

Odpowiedzi:

125

Musisz ustawić contentSizewłaściwość UIScrollView. Na przykład, jeśli twój UIScrollViewma 320 pikseli szerokości (szerokość ekranu), możesz to zrobić:

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

UIScrollViewWtedy tylko przewijać w pionie, ponieważ może już wyświetlać wszystko poziomo.

Dave DeLong
źródło
6
Cześć. To rozwiązanie działa naprawdę dobrze! Dziękuję za to. Próbowałem ustawić szerokość statyczną na 0. U mnie to też działa. Nie wiem, czy później mogą wystąpić jakieś skutki uboczne. Ale jeśli nie znasz rozmiaru (tj. Uniwersalny kod dla iPhone'a i iPada) to działa świetnie!
JackPearse
5
Myślę, że lepiej zrobić CGSizeMake (0, myScrollableHeight), więc przewijanie w poziomie jest wyłączone, nawet jeśli nie wszystkie podglądy zostały pokazane.
LightNight
Uwaga: Ustawienie jednego z wymiarów na 0 podczas korzystania ze stronicowania spowoduje, że VoiceOver ogłosi numer strony jako „strona 1 z 1” niezależnie od prawidłowej wartości
josef
1
Zamiast przekazywać szerokość jako 320 zakodowaną na stałe, możemy podać: CGSize scrollableSize = CGSizeMake (self.scrollview.frame.size.width, myScrollableHeight); [myScrollView setContentSize: scrollableSize];
Mohit kumar,
90

AKTUALIZACJA: (po tym, jak @EranMarom wskazał w swoim komentarzu)

Możesz zatrzymać przewijanie w poziomie lub w pionie w ScrollViewDelegatemetodzie. Oto jak,

Zatrzymuje przewijanie w poziomie:

Jeśli chcesz przewijać w poziomie, musisz zwiększyć contentOffset.x. Zapobieganie, które zatrzymuje przewijanie widoku w poziomie.

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

Zatrzymuje przewijanie w pionie:

Jeśli chcesz przewijać w pionie, musisz zwiększyć contentOffset.y. Zapobieganie, które zatrzymuje przewijanie widoku w pionie.

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

Powyższy kod uniemożliwia zmiany w xi ytematyce scrollview contentOffset, a to prowadzi do zatrzymania przewijania w scrollViewDidScroll:metodzie.

Dinesh Raja
źródło
1
Zastanawiam się nad obniżeniem głosów, ponieważ ta odpowiedź nie wyjaśnia, że ​​właśnie podałeś kod i to wszystko. Odpowiedz w ten sposób nie jest zbyt dobra. Dobra odpowiedź wyjaśnia się, podczas gdy doświadczeni programiści mogą zrozumieć, że nowi programiści mogą nie rozumieć, co się tutaj dzieje. Nie został jeszcze obniżony, ponieważ daje szansę na poprawę.
Popeye
14
To rodzaj włamania, ale zadziałało, gdy wszystko inne zawiodło. Więc +1, ale używaj tylko w ostateczności.
i_am_jorf
5
Ja też korzystam z tej metody delegata, ale zamieniam ciało na jednowierszowe, np .: scrollView.contentOffset = CGPointMake(0, scrollView.contentOffset.y);aby wyłączyć przewijanie w poziomie. Uważam, że jest bardziej czytelny, jest mniejszy i nie ma sensu robić testu dla zera, ponieważ praktycznie nie ma narzutu z kodem, który uruchamia się tak rzadko (tj. Maksymalnie kilkadziesiąt razy na sekundę).
Echelon
ponieważ zmieniasz zawartość Offset po "didscroll", a nie jak przed 'willscroll', i jest to rozwiązanie młotkiem, ale ja sam nie głosowałem przeciw, ponieważ 18 głosów za, a odpowiedź to 75, więc nie warto głosować przeciw
LolaRun
2
Jeszcze łatwiejsze jest użycie, scrollView.contentOffset.y = 0.0aby zatrzymać przewijanie w pionie i scrollView.contentOffset.x = 0.0zatrzymać przewijanie w poziomie w scrollViewDidScroll()funkcji delegata. Uważam jednak, że upewnienie się, że scrollView.contentSizerówna się scrollView.frame.sizeto jest lepszym (poprawnym) rozwiązaniem. Zobacz odpowiedź @danbeaulieu.
emem
11

od czasu użycia iOS7

self.automaticallyAdjustsScrollViewInsets = NO;

// i utwórz scroller strony z 3 stronami

    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
źródło
Nie sądzę, że spowoduje to wyłączenie przewijania widoku scrollview. Czy to jest ??
Dinesh Raja,
self.collectionView.pagingEnabled = YES;pomogło mi rozwiązać problem z płynnym przewijaniem (bez przeciągania). Problem scrollViewWillEndDragging:tkwił w metodzie - targetContentOffset był taki sam jak scrollView.contentOffset i logika wykrywania stron nie działa poprawnie.
podpis
11

Szybkie rozwiązanie

Utwórz dwa wyloty, jeden do widoku i jeden do widoku przewijania:

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

Następnie w swoim viewDidLayoutSubviews możesz dodać następujący kod:

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

To, co zrobiliśmy, to zebranie wysokości i szerokości widoku i ustawienie rozmiaru zawartości scrollViews, aby pasował do niego. Spowoduje to zatrzymanie przewijania widoku przewijania w poziomie.


Więcej myśli:

CGSizeMake pobiera szerokość i wysokość za pomocą CGFloats. Może być konieczne użycie istniejącej wysokości UIScrollViews dla drugiego parametru. Który wyglądałby tak:

let scrollSize = CGSize(width: myView.frame.size.width, 
                        height: scrollView.contentSize.height)
Dan Beaulieu
źródło
Co jeśli nie znasz wysokości lub szerokości (urządzenie uniwersalne)? @danbeaulieu
Lukesivi,
@lukesIvi „myView.frame.width” dynamicznie pobiera szerokość z IBOutlet „myView”.
Dan Beaulieu
4

W moim przypadku z Swift 4.2 możesz użyć:

Wyłącz przewijanie w pionie:

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

Wyłącz przewijanie w poziomie:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    scrollView.contentOffset.x = 0.0
}
Ricardo
źródło
3

Możesz wybrać widok, a następnie Attributes Inspectorodznaczyć User Interaction Enabled.

Coder221
źródło
3

W moim przypadku szerokość contentView była większa niż szerokość UIScrollView i to było przyczyną niechcianego przewijania w poziomie. Rozwiązałem to, ustawiając szerokość contentView równą szerokości UIScrollView.

Mam nadzieję, że to komuś pomoże

Gulfam Khan
źródło
@Nostradamus chętnie pomożemy
Gulfam Khan
0

Miałem ustawioną zawartość tableview w viewDidLoad (jak poniżej), która powoduje przewijanie w poziomie

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

Sprawdź, czy z różnych powodów ustawiono zestaw contentview widoku tabeli i wyłącz go

Naishta
źródło
0

Zmagałem się z tym przez jakiś czas próbując bezskutecznie różnych sugestii w tym i innych wątkach.

Jednak w innym wątku (nie jestem pewien, gdzie) ktoś zasugerował, że użycie negatywnego ograniczenia na UIScrollView zadziałało dla niego.

Wypróbowałem więc różne kombinacje ograniczeń z niespójnymi wynikami. Ostatecznie zadziałało dla mnie dodanie wiodących i końcowych ograniczeń -32 do widoku przewijania i dodanie (niewidocznego) widoku tekstowego o szerokości 320 (i wyśrodkowany).

Patricia W.
źródło
0

Spróbuj tego:

CGSize scrollSize = CGSizeMake([UIScreen mainScreen].bounds.size.width, scrollHeight);
[scrollView setContentSize: scrollSize];
Torongo
źródło
0

Wyłącz przewijanie w poziomie, zastępując contentOffsetwłaściwość w podklasie.

override var contentOffset: CGPoint {
  get {
    return super.contentOffset
  }
  set {
    super.contentOffset = CGPoint(x: 0, y: newValue.y)
  }
}
iWheelBuy
źródło
0

Wprowadzona w iOS 11 to nowa właściwość w UIScrollView

var contentLayoutGuide: UILayoutGuide

Dokumentacja stwierdza, że:

Użyj tego przewodnika po układzie, jeśli chcesz utworzyć ograniczenia automatycznego układu związane z obszarem zawartości widoku przewijania.

Wraz z innymi ograniczeniami autoLayout które można dodawać będziemy chcieli, aby powiązać widthAnchorz UIScrollView„s contentLayoutGuidebyć tej samej wielkości jako«ramy». Możesz użyć frameLayoutGuide(również wprowadzonej w iOS 11) lub dowolnej szerokości zewnętrznej (takiej jak Twoja superView).

przykład:

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

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

JMFR
źródło
-1

Kiedy już to zrobiłem, zastępując UIScrollView UITableView z tylko 1 komórką, działało dobrze.

Hola Soy Edu Feliz Navidad
źródło
1
Przepraszamy, to nie odpowiada na pytanie.
David
-1

Użyj tej pojedynczej linii.

self.automaticallyAdjustsScrollViewInsets = NO;

Karthickkck
źródło