美文网首页首页推荐iOS开发iOS程序猿
UITableView 下拉刷新的实现

UITableView 下拉刷新的实现

作者: 大美象 | 来源:发表于2017-03-12 15:30 被阅读304次

    UITableView下拉刷新的实现原理是自定义的下拉刷新控件KVO监听UITableView(UIScrollView)的 contentOffset 属性。

    #import <UIKit/UIKit.h>
    
    typedef void (^RefreshHeaderBlock)(void);
    
    @interface RefreshHeader : UIView
    
    - (instancetype)initWithTarget:(id)target beginRefreshBlock:(RefreshHeaderBlock)refreshHeaderBlock;
    
    - (void)beginRefreshing;
    
    - (void)endRefreshing;
    
    @end
    

    把UITableView(UIScrollView)传进来作为目标,添加监听

    @implementation RefreshHeader
    - (instancetype)initWithTarget:(id)target beginRefreshBlock:(RefreshHeaderBlock)refreshHeaderBlock{
        self = [super init];
        if (self) {
            self.frame = CGRectMake(0, 0, 0, HeaderHeight);
            _refreshHeaderBlock = refreshHeaderBlock;
    
            _scrollView = (UIScrollView *)target;
            [_scrollView addSubview:self];
            NSKeyValueObservingOptions option = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
            [_scrollView addObserver:self forKeyPath:RefreshHeaderKeyPathContentOffset options:option context:nil];
        }
        return self;
    }
    - (void)layoutSubviews{
        [super layoutSubviews];
        CGFloat superWidth = self.scrollView.frame.size.width;
        self.frame = CGRectMake(0, - HeaderHeight, superWidth, HeaderHeight);
        ......
    }
    
    #pragma mark public
    - (void)beginRefreshing{
        if (!_isRefresh) {
            
            _isRefresh = YES;
            
            //设置偏移量,衔接加载的更多数据
            [UIView animateWithDuration:0.3 animations:^{
                //刷新控件停留
                [_scrollView setContentInset:UIEdgeInsetsMake(HeaderHeight, 0, 0, 0)];
                
                [self.activityView startAnimating];
                self.arrowView.hidden = YES;
                self.stateLable.text = @"加载中";
            }];
            
            dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
                _refreshHeaderBlock();
            });
        }
    }
    
    - (void)endRefreshing{
        _isRefresh = NO;
        
        [UIView animateWithDuration:0.3 animations:^{
            [self.activityView stopAnimating];
            self.arrowView.hidden = YES;
            self.arrowView.transform =  CGAffineTransformMakeRotation(M_PI*2);
            
            //还原scrollView
            [self.scrollView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
        }];
    }
    
    #pragma mark KVO
    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
        if ([keyPath isEqualToString:RefreshHeaderKeyPathContentOffset]) {
            [self scrollViewContentOffsetDidChange:change];
        }else{
            [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
        }
    }
    
    #pragma mark logicol
    //判断contentOffset<0代表手势为往下拖动,根据isDragging属性判断是否松开,如果松开且偏移量大于(HeaderHeight),启动刷新动作
    - (void)scrollViewContentOffsetDidChange:(NSDictionary *)change{
        
        self.stateLable.hidden = NO;
        CGFloat offset = self.scrollView.contentOffset.y;
        if (offset < 0) {
            //正在拖拽
            if(self.scrollView.isDragging){
                //还原scrollView
                [self.scrollView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
                
                [UIView animateWithDuration:0.3 animations:^{
                    self.arrowView.hidden = NO;
                    if (offset < -HeaderHeight*1.5) {
                        self.arrowView.transform =  CGAffineTransformMakeRotation(M_PI);
                        self.stateLable.text = @"释放更新";
                    }else{
                        self.arrowView.transform =  CGAffineTransformMakeRotation(M_PI*2);
                        self.stateLable.text = @"载入更多";
                    }
                }];
                
                return;
            }
            
            //松开且偏移量大于头部高度,启动刷新
            if (offset < -HeaderHeight) {
                [self beginRefreshing];
            }
        }
    }
    
    -(void)dealloc{
        [self.scrollView removeObserver:self forKeyPath:RefreshHeaderKeyPathContentOffset];
    }
    
    

    demo

    相关文章

      网友评论

        本文标题:UITableView 下拉刷新的实现

        本文链接:https://www.haomeiwen.com/subject/jbntnttx.html