iOS ScrollView 下拉放大 升级 带上下拉刷新

在上一篇《iOS ScrollView 下拉放大》已经介绍了基本的下拉放大,接下来再加上下拉刷新

定义下拉刷新状态

typedef enum {

    RefreshStateIdle,

    RefreshStatePullRefresh,

    RefreshStateReadyRefresh,

    RefreshStateRefreshing


} RefreshState;

 

定义下拉刷新需使用的变量

{
    
    // Refresh
    UILabel *_refreshLabel;
    RefreshState _refreshState;
    CGFloat _refreshHeight;
}

下拉刷新的实现是在下拉刷的新阀值detal小于下拉放大阀值alpha的基础上进行的,接下来就初始化下拉刷新的变量了

    _refreshState = RefreshStateIdle;
    _refreshHeight = 40;
    
    _refreshLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, -    
    _refreshHeight, self.view.bounds.size.width, _refreshHeight)];
    _refreshLabel.textAlignment = NSTextAlignmentCenter;
    _refreshLabel.textColor = [UIColor redColor];
    _refreshLabel.text = @"刷新...";
    [self.view addSubview:_refreshLabel];

然后改造ScrollView代理方法了,在处理下拉放大的过程中同时处理下拉刷新

#pragma mark - ScrollView Delegate

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    
    if (_refreshState == RefreshStateRefreshing) {
        return;
    }
    
    CGFloat offsetY = scrollView.contentOffset.y;
    NSLog(@"offsetY: %f",offsetY);
    
    CGFloat top = scrollView.contentInset.top;
    
    if (!_zoomIn) {
        if (offsetY < -top) { // 下拉
            CGRect frame = _zoomView.frame;
            frame.origin.y = offsetY;
            frame.size.height = -offsetY;
            _zoomView.frame = frame;
            
            // 处理下拉
            if (_refreshState != RefreshStateRefreshing && !_decelerating) {
                frame = _refreshLabel.frame;
                frame.origin.y = -offsetY - top;
                _refreshLabel.frame = frame;
                
                if ((-offsetY - top) < _refreshHeight) {
                    [self setRefreshState:RefreshStatePullRefresh];
                } else {
                    [self setRefreshState:RefreshStateReadyRefresh];
                }
            }
            
            
            if (!_decelerating && -offsetY > 1.9 * _zoomHeight) {
                
                [self setRefreshState:RefreshStateIdle];
                frame.origin.y = -_refreshHeight;
                _refreshLabel.frame = frame;
                
                scrollView.contentInset = UIEdgeInsetsMake(scrollView.bounds.size.height, 0, 0, 0);
                frame.origin.y = -scrollView.bounds.size.height;
                frame.size.height = scrollView.bounds.size.height;
                _zoomView.frame = frame;
                
                _zoomIn = YES;
                scrollView.contentSize = CGSizeMake(0, 1); // 使上拉有弹簧效果
            }
        }
    } else { // 上拉
        if (!_decelerating && (offsetY + top) / top > 0.3) {
            
            scrollView.contentInset = UIEdgeInsetsMake(_zoomHeight, 0, 0, 0);
            CGRect frame = _zoomView.frame;
            frame.origin.y = -_zoomHeight;
            frame.size.height = _zoomHeight;
            _zoomView.frame = frame;
            
            _zoomIn = NO;
            scrollView.contentSize = CGSizeMake(0, _contentSize.height); // 恢复正常
        }
    }

}

- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView {
    _decelerating = YES;
}

- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    _decelerating = NO;
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    
    if (_refreshState == RefreshStateRefreshing) {
        return;
    }
    
    CGRect frame = _refreshLabel.frame;
    if (_refreshState == RefreshStateReadyRefresh) {
        [self setRefreshState:RefreshStateRefreshing];
        frame.origin.y = 0;
    } else {
        [self setRefreshState:RefreshStateIdle];
        frame.origin.y = -_refreshHeight;
    }
    _refreshLabel.frame = frame;
}

#pragma mark - Refresh

- (void)setRefreshState:(RefreshState)state {
    _refreshState = state;
    
    if (_refreshState == RefreshStateIdle) {
        _refreshLabel.text = @"下拉刷新";
    } else if (_refreshState == RefreshStatePullRefresh) {
        _refreshLabel.text = @"下拉刷新";
    } else if (_refreshState == RefreshStateReadyRefresh) {
        _refreshLabel.text = @"松开刷新";
    } else if (_refreshState == RefreshStateRefreshing) {
        _refreshLabel.text = @"刷新...";
        [self loadData];
    }
}

处理滑动的过程中,如果当前正在刷新那么立即返回。下拉过程中根据offsetY值判断到达阀值,在到达刷新阀值detal后并且没有达到放大阀值alpha,那么松手的时候就进入刷新状态,没有达到下拉刷新阀值detal就松手的情况下就恢复正常。如果在达到下拉刷新阀值detal后继续下拉到达放大阀值,那么就将刷新状态置为idle,同时隐藏刷新View,做放大操作。

当然,刷新完成后还要报告刷新完成,以处理刷新View

#pragma mark - Load Data

- (void)loadData {
    
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
       
        sleep(5);
        
        dispatch_async(dispatch_get_main_queue(), ^{
            if (weakSelf) {
                __strong typeof(weakSelf) strongSelf = weakSelf;
                
                [strongSelf refreshFinish];
            }
            
        });
        
    });
}

- (void)refreshFinish {
    
    [self setRefreshState:RefreshStateIdle];
    CGRect frame = _refreshLabel.frame;
    frame.origin.y = -_refreshHeight;
    _refreshLabel.frame = frame;
}

 

posted @ 2018-05-18 13:59  Emerys  阅读(1172)  评论(0编辑  收藏  举报