UIScrollView, достигающий нижней части прокрутки

#iphone #uiscrollviewdelegate

#iPhone #uiscrollviewdelegate

Вопрос:

Я знаю, что в документации Apple есть следующий метод делегирования:

 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;      // called when scroll view grinds to a halt
  

Однако это не обязательно означает, что вы находитесь внизу. Потому что, если вы используете палец, немного прокручиваете, затем это замедляется, но на самом деле вы не находитесь в нижней части экрана прокрутки, тогда он все равно вызывается. Я в основном хочу, чтобы стрелка показывала, что в моем режиме прокрутки больше данных, а затем исчезала, когда вы находитесь внизу (например, когда она отскакивает). Спасибо.

Ответ №1:

Я думаю, что вы могли бы сделать, это проверить, находится ли ваша contentOffset точка внизу contentSize . Таким образом, вы, вероятно, могли бы сделать что-то вроде:

 - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    float bottomEdge = scrollView.contentOffset.y   scrollView.frame.size.height;
    if (bottomEdge >= scrollView.contentSize.height) {
        // we are at the end
    }
}
  

Вероятно, вам также понадобится отрицательный регистр, чтобы отобразить ваш индикатор, когда пользователь прокручивает его обратно. Возможно, вы также захотите добавить к этому некоторые дополнения, чтобы, например, вы могли скрыть индикатор, когда пользователь находится в нижней части, но не совсем внизу.

Комментарии:

1. Лучшее решение, но я бы поместил его в — (void)scrollViewDidScroll:(UIScrollView *)ScrollView{} вместо этого

2. @MobileMon прав, его следует использовать в scrollViewDidScroll методе.

3. Как раз те строки, которые я искал. Работает и с UICollectionView.

4. Если вы готовы поместить свою логику внутрь scrollViewDidScroll , вам нужно разработать какой-нибудь защитный флаг, который предотвратит запуск вашей логики миллион раз. Это потому, что у вас есть >= там, и оно будет успешно попадать внутрь if предложения миллион раз, когда ваше табличное представление отскакивает. Гораздо лучше наблюдать за окончанием замедления, поскольку оно вызывается после завершения отскока

5. scrollViewDidEndDecelerating не запускается, если я вызываю: cv.scrollToBottom()

Ответ №2:

Итак, если вы хотите это в swift, вот и все:

 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 amp;amp; scrollView.contentOffset.y < (scrollView.contentSize.height - scrollView.frame.size.height)){
        //not top and not bottom
    }
}
  

Ответ №3:

Я думаю, что ответ @bensnider правильный, но не exart. По этим двум причинам

 1. - (void)scrollViewDidScroll:(UIScrollView *)scrollView{}
  

Этот метод будет вызываться непрерывно, если мы проверяем наличие if (bottomEdge >= scrollView.contentSize.height)

2 . В этом случае, если мы перейдем к == проверке, это условие также будет действовать два раза.

  • (i) когда мы будем прокручивать вверх, когда конец прокрутки касается нижнего края
  • (ii) Когда scrollview отскакивает назад, чтобы сохранить свое собственное положение

Я чувствую, что это более точно.

В очень немногих случаях эта кодировка действительна и для двух раз. Но пользователь не столкнется с этим.

 - (void)scrollViewDidScroll:(UIScrollView *)scrollView
 {
    if (scrollView.contentOffset.y == roundf(scrollView.contentSize.height-scrollView.frame.size.height)) {
    NSLog(@"we are at the endddd");

   //Call your function here...

    }
}
  

Комментарии:

1. Да, это должен был быть принятый ответ. Кроме того, я думаю, что в уравнении следует использовать коэффициент contentScale

Ответ №4:

Принятый ответ работает, только если нижнее contentInset значение неотрицательно. Небольшая эволюция будет учитывать нижнюю часть contentInset независимо от его знака:

 CGFloat bottomInset = scrollView.contentInset.bottom;
CGFloat bottomEdge = scrollView.contentOffset.y   scrollView.frame.size.height - bottomInset;
if (bottomEdge == scrollView.contentSize.height) {
    // Scroll view is scrolled to bottom
}
  

Ответ №5:

На самом деле, вместо того, чтобы просто помещать код @bensnider в scrollViewDidScroll, этот код (написанный на Swift 3) был бы более производительным с точки зрения производительности:

 func scrollViewDidEndDragging(_ scrollView: UIScrollView,
                              willDecelerate decelerate: Bool) {
    if !decelerate {
        checkHasScrolledToBottom()
    }
}

func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
    checkHasScrolledToBottom()
}

func checkHasScrolledToBottom() {
    let bottomEdge = scrollView.contentOffset.y   scrollView.frame.size.height
    if bottomEdge >= scrollView.contentSize.height {
        // we are at the end
    }
}
  

Ответ №6:

Это работает в Swift 3 :

 override func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if scrollView.contentOffset.y == (scrollView.contentSize.height - scrollView.frame.size.height) {
        loadMore()
    }
}
  

Ответ №7:

Посмотрите, какие элементы в данный момент отображаются в UIView, используя что-то вроде indexPathsForVisibleRows , и если в вашей модели больше элементов, чем отображается, поместите стрелку внизу.