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的控件下拉刷新集成。每多读一次代码就有一次新的收获。还等什么,赶紧去敲出来吧。