Как я могу проверить, является ли представление прокрутки подпрыгивающим? - PullRequest
13 голосов
/ 18 мая 2010

Как я могу проверить, является ли прыгающий вид прокрутки? Есть ли уведомление или что-то еще, когда отскок заканчивается?

Ответы [ 7 ]

31 голосов
/ 27 января 2012

Вот как я обнаружил, если представление прокрутки отскакивает горизонтально:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {

  if (scrollView.contentOffset.x < 0) {
    NSLog(@"bouncing left");
  }

  if (scrollView.contentOffset.x > (scrollView.contentSize.width - scrollView.frame.size.width)) {
    NSLog(@"bouncing right");
  }
}
24 голосов
/ 22 марта 2017

Я реализовал расширение для UIScrollView, чтобы справиться с этим для вертикальной и горизонтальной прокрутки. Это будет работать даже с ненулевым contentInsets и в случае, когда контент недостаточно велик для покрытия вставок scrollView:

Objective-C

@interface UIScrollView (Bouncing)

@property (nonatomic, readonly) BOOL isBouncing;
@property (nonatomic, readonly) BOOL isBouncingTop;
@property (nonatomic, readonly) BOOL isBouncingLeft;
@property (nonatomic, readonly) BOOL isBouncingBottom;
@property (nonatomic, readonly) BOOL isBouncingRight;

@end

@implementation UIScrollView (Bouncing)

- (BOOL)isBouncing
{
    return self.isBouncingTop || self.isBouncingLeft || self.isBouncingBottom || self.isBouncingRight;
}

- (BOOL)isBouncingTop
{
    return self.contentOffset.y < - self.contentInset.top;
}

- (BOOL)isBouncingLeft
{
    return self.contentOffset.x < - self.contentInset.left;
}

- (BOOL)isBouncingBottom
{
    BOOL contentFillsScrollEdges = self.contentSize.height + self.contentInset.top + self.contentInset.bottom >= CGRectGetHeight(self.bounds);
    return contentFillsScrollEdges && self.contentOffset.y > self.contentSize.height - CGRectGetHeight(self.bounds) + self.contentInset.bottom;
}

- (BOOL)isBouncingRight
{
    BOOL contentFillsScrollEdges = self.contentSize.width + self.contentInset.left + self.contentInset.right >= CGRectGetWidth(self.bounds);
    return contentFillsScrollEdges && self.contentOffset.x > self.contentSize.width - CGRectGetWidth(self.bounds) + self.contentInset.right;
}

@end

Swift 3.0 +

extension UIScrollView {
  var isBouncing: Bool {
    return isBouncingTop || isBouncingLeft || isBouncingBottom || isBouncingRight
  }
  var isBouncingTop: Bool {
    return contentOffset.y < -contentInset.top
  }
  var isBouncingLeft: Bool {
    return contentOffset.x < -contentInset.left
  }
  var isBouncingBottom: Bool {
    let contentFillsScrollEdges = contentSize.height + contentInset.top + contentInset.bottom >= bounds.height
    return contentFillsScrollEdges && contentOffset.y > contentSize.height - bounds.height + contentInset.bottom
  }
  var isBouncingRight: Bool {
    let contentFillsScrollEdges = contentSize.width + contentInset.left + contentInset.right >= bounds.width
    return contentFillsScrollEdges && contentOffset.x > contentSize.width - bounds.width + contentInset.right
  }
}

Для RxSwift вы можете просто сопоставить scrollViewDidScroll с isBouncing и фильтровать с distinctUntilChanged.

9 голосов
/ 22 ноября 2012

Незначительная поправка к методу Джастина, допускающая contentInset:

if( scrollView.contentOffset.x < -scrollView.contentInset.left )
{
    NSLog( @"bounce left" );
}
if( scrollView.contentOffset.x > scrollView.contentSize.width - scrollView.frame.size.width + scrollView.contentInset.right )
{
    NSLog( @"bounce right" );
}
7 голосов
/ 18 мая 2010

Да ... проверьте спецификацию UIScrollViewDelegate, реализуйте методы, включая два ниже, и соответственно установите делегата вашего UIScrollView:

// User stops dragging the table view.

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView
    willDecelerate:(BOOL)decelerate;

// Control slows to a halt after the user drags it

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView;

Вероятно, вас больше всего заинтересует scrollViewDidEndDecelerating. Они также работают в UITableView, где я их и нашел (UITableView наследует от UIScrollView).

2 голосов
/ 16 января 2014

Старый вопрос, но я только что столкнулся с подобной проблемой и хотел добавить, что неплохо также проверить, что содержимое представлений прокрутки больше, чем рамка представления прокрутки:

+ (BOOL) isScrollViewBouncing:(UIScrollView *)scrollView
{
    return scrollView.contentOffset.y > scrollView.contentSize.height - scrollView.frame.size.height
            && scrollView.contentSize.height > scrollView.frame.size.height;
}

Теперь это гарантирует, что представление прокрутки достаточно велико, чтобы находиться в состоянии отскока прокрутки, так что если представление прокрутки мало, оно НЕ всегда будет иметь значение true.

Приветствия

1 голос
/ 25 июля 2013

Для тех из вас, кто сможет «отскочить» вниз в виде прокрутки, чтобы обновить содержимое представления. (И событие запускается только один раз.)

- (void)scrollViewDidEndDragging:(UIScrollView *)aScrollView
                  willDecelerate:(BOOL)decelerate{

    CGPoint offset = aScrollView.contentOffset;
    CGRect bounds = aScrollView.bounds;
    CGSize size = aScrollView.contentSize;
    UIEdgeInsets inset = aScrollView.contentInset;
    float y = offset.y + bounds.size.height - inset.bottom;
    float h = size.height;

    //Distance in points before update-event occur
    float reload_distance = 50;
    //
    if(y > h + reload_distance) {
        NSLog(@"load more rows");
    }
}
0 голосов
/ 23 марта 2016

Используя ответ Главида, я также добавил подпрыгивание внизу и добавил как категорию

#import "UIScrollView+Additions.h"

@implementation UIScrollView (Additions)

- (BOOL)isBouncing
{
    BOOL isBouncingBottom = self.contentOffset.y >= self.contentSize.height - self.frame.size.height
        && self.contentSize.height >= self.frame.size.height;
    BOOL isBouncingTop = self.contentOffset.y <= 0;

    BOOL isBouncing = isBouncingBottom || isBouncingTop;
    return isBouncing;
}

@end
...