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ąć?


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.


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.


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

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)

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
}

3

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


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


@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


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).


0

Spróbuj tego:

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

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)
  }
}

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



Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.