iPhone - знаючи, чи досягнув UIScrollView зверху чи знизу


Відповіді:


198

Впровадьте UIScrollViewDelegateу свій клас, а потім додайте це:

-(void)scrollViewDidScroll: (UIScrollView*)scrollView
{
    float scrollViewHeight = scrollView.frame.size.height;
    float scrollContentSizeHeight = scrollView.contentSize.height;
    float scrollOffset = scrollView.contentOffset.y;

    if (scrollOffset == 0)
    {
        // then we are at the top
    }
    else if (scrollOffset + scrollViewHeight == scrollContentSizeHeight)
    {
        // then we are at the end
    }
}

Сподіваюся, це те, що ви шукаєте! В іншому є майстерність, додавши більше умов до вищезазначеного коду та NSLog значення scrollOffset.


4
Якщо ви перебуваєте у navigationController, ви можете зробити щось подібне: scrollOffset <= (0 - self.navigationController.navigationBar.frame.size.height - 20)і(scrollOffset + scrollHeight) >= scrollContentSizeHeight
Уейн

Проблема в цьому полягає в відскакуванні ... все, що викликається двічі, один раз досягає верху або низу. Чи є таке рішення, крім вимкнення відмови таблиці або колекції?
denikov

@denikov ти знайшов якесь рішення для цього?
Приял

83

Ну, contentInsetsтакож беруть участь, коли ви намагаєтесь визначити, чи є scrollView вгорі чи внизу. Ви також можете бути зацікавлені в тих випадках , коли ваш Scrollview знаходиться вище верхньої і нижче нижньої. Ось код, який я використовую для пошуку верхньої та нижньої позицій:

Стрімкий:

extension UIScrollView {

    var isAtTop: Bool {
        return contentOffset.y <= verticalOffsetForTop
    }

    var isAtBottom: Bool {
        return contentOffset.y >= verticalOffsetForBottom
    }

    var verticalOffsetForTop: CGFloat {
        let topInset = contentInset.top
        return -topInset
    }

    var verticalOffsetForBottom: CGFloat {
        let scrollViewHeight = bounds.height
        let scrollContentSizeHeight = contentSize.height
        let bottomInset = contentInset.bottom
        let scrollViewBottomOffset = scrollContentSizeHeight + bottomInset - scrollViewHeight
        return scrollViewBottomOffset
    }

}

Завдання-C:

@implementation UIScrollView (Additions)

- (BOOL)isAtTop {
    return (self.contentOffset.y <= [self verticalOffsetForTop]);
}

- (BOOL)isAtBottom {
    return (self.contentOffset.y >= [self verticalOffsetForBottom]);
}

- (CGFloat)verticalOffsetForTop {
    CGFloat topInset = self.contentInset.top;
    return -topInset;
}

- (CGFloat)verticalOffsetForBottom {
    CGFloat scrollViewHeight = self.bounds.size.height;
    CGFloat scrollContentSizeHeight = self.contentSize.height;
    CGFloat bottomInset = self.contentInset.bottom;
    CGFloat scrollViewBottomOffset = scrollContentSizeHeight + bottomInset - scrollViewHeight;
    return scrollViewBottomOffset;
}


@end

Це хороша відповідь, реалізація scrollviewdidscroll погано впливає на результати
Василь

3
Як я можу це назвати, якщо не використовую scrollViewDidScroll?
Dave G

2
Через примхи математики з плаваючою комою, я отримував "verticalOffsetForBottom" 1879.05xxx і мій contentOffset.y був 1879, коли знаходився внизу в Swift 3. Тож я змінився return scrollViewBottomOffsetнаreturn scrollViewBottomOffset.rounded()
chadbag

1
Станом на iOS 11 це safeAreaInsetsтакож враховується. scrollView.contentOffset.y + scrollView.bounds.height - scrollView.safeAreaInsets.bottom
InkGolem

35

Якщо ви хочете швидко ввести код:

override func scrollViewDidScroll(scrollView: UIScrollView) {

    if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) {
        //reach bottom
    }

    if (scrollView.contentOffset.y <= 0){
        //reach top
    }

    if (scrollView.contentOffset.y > 0 && scrollView.contentOffset.y < (scrollView.contentSize.height - scrollView.frame.size.height)){
        //not top and not bottom
    }
}


4

Я точно зрозумів, як це зробити:

CGFloat maxPosition = scrollView.contentInset.top + scrollView.contentSize.height + scrollView.contentInset.bottom - scrollView.bounds.size.height;
CGFloat currentPosition = scrollView.contentOffset.y + self.topLayoutGuide.length;

if (currentPosition == maxPosition) {
  // you're at the bottom!
}

0

Зробіть це так (для Swift 3):

class MyClass: UIScrollViewDelegate {

   func scrollViewDidScroll(_ scrollView: UIScrollView) {

        if (scrollView.contentOffset.y >= (scrollView.contentSize.height - scrollView.frame.size.height)) {
           //scrolled to top, do smth
        }


    }
}

Ласкаво просимо до SO! Розміщуючи код у своїй відповіді, корисно пояснити, як ваш код вирішує проблему ОП :)
Джоел,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.