浅谈对MJRefresh(上)下拉刷新控件的理解

MJRefresh GitHub地址:https://github.com/CoderMJLee/MJRefresh

利用业余时间研究了一下iOS的开发,发现OC特定的语法方式吸引了我,而且iOS开发中有很多有趣的东西,正是如此,重新激起了我对开发学习的兴趣。自学过程中,知道了这个MJRefresh,MJ真乃大神也。

废话不多说,MJRefresh集成了UIView,UICollectionView,UITableView的上下拉刷新功能,而且还有自定义文字,动画等功能。针对GitHub上的源代码研究了一翻,打算照抄一遍,理解里面的机制并且期待能从自己的实战中学到新的东西。相信敲完一遍之后对它的理解又是一个新的层次。

MJRefresh的结构大致是这样子的:

MJRefreshComponent自然是父类,它定义了基本的文字大小,颜色,刷新事件,block,以及开始刷新,结束刷新等基本操作和属性。

 1 @interface MJRefreshComponent : UIView
 2 {
 3     UIEdgeInsets _scrollViewOriginalInset;
 4     __weak UIScrollView *_scrollView;
 5 }
 6 
 7 #pragma mark - 文字处理
 8 /** 文字颜色 */
 9 @property (strong, nonatomic) UIColor *textColor;
10 /** 字体大小 */
11 @property (strong, nonatomic) UIFont *font;
12 
13 #pragma mark - 刷新处理
14 /** 正在刷新的回调 */
15 @property (copy, nonatomic) void (^refreshingBlock)();
16 /** 设置回调对象和回调方法 */
17 - (void)setRefreshingTarget:(id)target refreshingAction:(SEL)action;
18 @property (weak, nonatomic) id refreshingTarget;
19 @property (assign, nonatomic) SEL refreshingAction;
20 /** 进入刷新状态 */
21 - (void)beginRefreshing;
22 /** 结束刷新状态 */
23 - (void)endRefreshing;
24 /** 是否正在刷新 */
25 - (BOOL)isRefreshing;
26 @end

我个人认为,最重要的两个类就是 MJRefreshHeader和MJRefreshFooter。因为刷新事件的精髓就在这两个类里面,Footer不多做介绍。我个人理解是,主要通过KVO监听 contentOffSet属性变化来判断当时是否是刷新、还是下拉、还是正在刷新或者改变刷新状态,核心代码当然我还是因为自身水平的原因没太看懂,相信敲完一遍之后会明白吧。核心代码如下:

#pragma mark 根据contentOffset调整state
- (void)adjustStateWithContentOffset
{
    if (self.state != MJRefreshHeaderStateRefreshing) {
        // 在刷新过程中,跳转到下一个控制器时,contentInset可能会变
        _scrollViewOriginalInset = _scrollView.contentInset;
    }
    
    // 在刷新的 refreshing 状态,动态设置 content inset
    if (self.state == MJRefreshHeaderStateRefreshing ) {
        if(_scrollView.contentOffset.y >= -_scrollViewOriginalInset.top ) {
            _scrollView.mj_insetT = _scrollViewOriginalInset.top;
        } else {
            _scrollView.mj_insetT = MIN(_scrollViewOriginalInset.top + self.mj_h,
                                        _scrollViewOriginalInset.top - _scrollView.contentOffset.y);
        }
        return;
    }
    
    // 当前的contentOffset
    CGFloat offsetY = _scrollView.mj_offsetY;
    // 头部控件刚好出现的offsetY
    CGFloat happenOffsetY = - _scrollViewOriginalInset.top;
    
    // 如果是向上滚动到看不见头部控件,直接返回
    if (offsetY >= happenOffsetY) return;
    
    // 普通 和 即将刷新 的临界点
    CGFloat normal2pullingOffsetY = happenOffsetY - self.mj_h;
    if (_scrollView.isDragging) {
        self.pullingPercent = (happenOffsetY - offsetY) / self.mj_h;
        
        if (self.state == MJRefreshHeaderStateIdle && offsetY < normal2pullingOffsetY) {
            // 转为即将刷新状态
            self.state = MJRefreshHeaderStatePulling;
        } else if (self.state == MJRefreshHeaderStatePulling && offsetY >= normal2pullingOffsetY) {
            // 转为普通状态
            self.state = MJRefreshHeaderStateIdle;
        }
    } else if (self.state == MJRefreshHeaderStatePulling) {// 即将刷新 && 手松开
        self.pullingPercent = 1.0;
        // 开始刷新
        self.state = MJRefreshHeaderStateRefreshing;
    } else {
        self.pullingPercent = (happenOffsetY - offsetY) / self.mj_h;
    }
}

最后呢,通过UIScrollView+MJRefresh扩展来实现UIScrollView的控件下拉刷新集成。每多读一次代码就有一次新的收获。还等什么,赶紧去敲出来吧。

posted @ 2015-12-03 11:07  丶Pz  阅读(1737)  评论(0编辑  收藏  举报