Mam UIView
podobny do iPhone'a Springboard. Stworzyłem go za pomocą UIScrollView
i UIButtons
. Chcę wyłączyć przewijanie w poziomie we wspomnianym widoku przewijania. Chcę tylko przewijania w pionie. Jak to osiągnąć?
Mam UIView
podobny do iPhone'a Springboard. Stworzyłem go za pomocą UIScrollView
i UIButtons
. Chcę wyłączyć przewijanie w poziomie we wspomnianym widoku przewijania. Chcę tylko przewijania w pionie. Jak to osiągnąć?
Odpowiedzi:
Musisz ustawić contentSize
właściwość UIScrollView
. Na przykład, jeśli twój UIScrollView
ma 320 pikseli szerokości (szerokość ekranu), możesz to zrobić:
CGSize scrollableSize = CGSizeMake(320, myScrollableHeight);
[myScrollView setContentSize:scrollableSize];
UIScrollView
Wtedy tylko przewijać w pionie, ponieważ może już wyświetlać wszystko poziomo.
AKTUALIZACJA: (po tym, jak @EranMarom wskazał w swoim komentarzu)
Możesz zatrzymać przewijanie w poziomie lub w pionie w ScrollViewDelegate
metodzie. 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 x
i y
tematyce scrollview contentOffset
, a to prowadzi do zatrzymania przewijania w scrollViewDidScroll:
metodzie.
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ę).
scrollView.contentOffset.y = 0.0
aby zatrzymać przewijanie w pionie i scrollView.contentOffset.x = 0.0
zatrzymać przewijanie w poziomie w scrollViewDidScroll()
funkcji delegata. Uważam jednak, że upewnienie się, że scrollView.contentSize
równa się scrollView.frame.size
to jest lepszym (poprawnym) rozwiązaniem. Zobacz odpowiedź @danbeaulieu.
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];
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.
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)
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
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).
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ć widthAnchor
z UIScrollView
„s contentLayoutGuide
być 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
Kiedy już to zrobiłem, zastępując UIScrollView UITableView z tylko 1 komórką, działało dobrze.
Użyj tej pojedynczej linii.
self.automaticallyAdjustsScrollViewInsets = NO;