MJRefresh-header
header的使用
self.tableView.header = [MJRefreshNormalHeader headerWithRefreshingTarget:self refreshingAction:@selector(loadNewData)];
或:
self.tableView.header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
}];
在mj2.0上, 属性名改为mj_header : self.tableView.mj_header。 如果不想把工程所有的header改成mj_header ,就把 从UIScrollView (MJRefresh)的.h中,去掉
MJRefreshDeprecated("使用mj_header")。mj_footer同理。
1. 从UIScrollView (MJRefresh) 讲起
利用关联,给UIScrollView添加属性 mj_header 和mj_footer。在其set方法当中,[self insertSubview:mj_header atIndex:0];
利用runtime的方法置换 ,将mj_reloadData替换reloadData方法,并新添返回row的数量或者是item的数量方法。
2.MJ的基类 MJRefreshComponent
这个类,主要的作用就是初始化。
1.定义state =idle;
2.当self.tableView.header 或self.tableView.footer的set方法进行调用时,willMoveToSuperview就会调用。 在这里,将scrollview的contentOffset 和contentSize进行监听。将scrollview的pan手势 属性state 也进行监听。
3.实现- (void)beginRefreshing 和- (void)endRefreshing 方法 并设置相应的state
4.实现回调 self.refreshingBlock(); 或者MJRefreshMsgSend(MJRefreshMsgTarget(self.refreshingTarget), self.refreshingAction, self);//objc_msgSend方法
3.MJRefreshHeader
继承了父类MJRefreshComponent的几个方法
1).初始化 prepare placeSubviews
2).- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change//监听ContentOffset
判断self.scrollView.contentOffset.y 和 - self.scrollViewOriginalInset.top -54的大小设置状态。同时,跟MJRefreshBackFootet一样,不是自动刷新,换句话说,不会随着滑动惯性滑到顶部时就更新了,而是要专门的往下拖,
self.scrollView.isDragging=no时才可以。
当state== Refreshing时,inset = max(self.scrollView.contentOffset.y,scrollView.contentInset.top). inset = max(54+scrollView.contentInset.top,inset);
然后将self.scrollView.content.inset = inset;
3).- (void)setState:(MJRefreshState)state
当state==idle时,先将时间保存。然后设置self.scrollView.contentSize.top
当state==Refreshings时,增加滚动区域top和回复contentOffSet
4.MJRefreshStateHeader
-setLastUpdatedTimeKey lastUpdatedTimeLabel的set方法,设置显示更新时间。
初始化时,将文案通过状态 MJRefreshState都放到 stateTitles 字典中,取时根据状态获取相应的文案。
这个view主要是设置文案,含有状态的文字。
5.MJRefreshNormalHeader 默认的下拉控件
_arrowView 箭头的imageview
loadingView 转圈圈的 UIActivityIndicatorView。
同样在 - (void)setState:(MJRefreshState)state 方法中,改变 arrowView 的方向或者loadingView的显示。
6.MJRefreshGifHeader 带动图的
- (void)setImages:(NSArray *)images forState:(MJRefreshState)state;
根据不同的状态 设置含有图片的数组。也可以设置间隔时间
- (void)setImages:(NSArray *)images duration:(NSTimeInterval)duration forState:(MJRefreshState)state
重写 setPullingPercent 根据进度 获得数组的坐标。
最后,在 setState 方法中,使用imageview自带的方式,实现动画效果。
其关系如图所示:
header 总结
初始化
1.init时,设置state==idle
2.给 UIScrollView (MJRefresh) 的setMj_header 中 调用 [self insertSubview:mj_header atIndex:0];
3. MJRefreshComponent 中 - (void)willMoveToSuperview: 记录contentInset 。并对scrollview 进行kvo监听
下拉
1.contentOffset 发生改变, MJRefreshHeader中 - (void)scrollViewContentOffsetDidChange:(NSDictionary *)change
计算偏移量并设置相应的state。
1.将偏移量和54进行比较 state=pulling
2.MJRefreshHeader [self beginRefreshing]; 父类调用 state=refreshing 设置scrollview.contentinset
在 - (void)setState:(MJRefreshState)state 中,也设置scrollview.contentinset。
3.<54时 state=idle
2.调用 endRefreshing 调用父类 endRefreshing state=idle
在- (void)setState:(MJRefreshState)state中,保留时间,将scrollview.contentinset =0
MJRefresh-footer :
1.MJRefreshFooter
1).初始化。
2).- (void)willMoveToSuperview:(UIView *)newSuperview 当row的数量和item的数量为0时,隐藏。
2.MJRefreshAutoFooter
1).- (void)willMoveToSuperview:(UIView *)newSuperview //设置self.scrollView.ContentSize.Bottom +=44;
2).- (void)scrollViewContentSizeDidChange:(NSDictionary *)change //footer.y = self.scrollView.ContentSize.height;
3).- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change //先判断内容是否超过一屏,
偏移量 > (content inset.height - 屏幕高+44*1 +content inset.bottom-44
)之后调用beginRefreshing
4).- (void)scrollViewPanStateDidChange:(NSDictionary *)change //
5).- (void)setState:(MJRefreshState)state //state==refreshing时,回调。
3.MJRefreshAutoStateFooter 设置字体的
4.MJRefreshAutoNormalFooter 设置UIActivityIndicatorView的
5.MJRefreshAutoGifFooter 设置动画的,用UIImageView实现。
2-1 MJRefreshBackFooter
1).- (void)willMoveToSuperview:(UIView *)newSuperview //调用scrollViewContentSizeDidChange
2).- (void)scrollViewContentOffsetDidChange:(NSDictionary *)change
a = self.scrollView.mj_offsetY ;
b = self.scrollView.contentSize - self.scrollView.frame.size.height;
c = b+44 ;
1.判断state && a > c 设置为pulling状态
2.判断 self.scrollView.isDragging= NO 且state==pulling. //同MJRefreshHeader一样
3).- (void)scrollViewContentSizeDidChange:(NSDictionary *)change //设置footer.y
4).- (void)setState:(MJRefreshState)state
当为idle时,设置回contentSize.bottom
当为refreshing时,contentSize.bottom +=44;contentOffSize.y = b+44;
3-1 MJRefreshBackStateFooter 设置字体的
4-1 MJRefreshBackNormalFooter 设置UIActivityIndicatorView的
5-1 MJRefreshBackGifFooter 设置动画的,用UIImageView实现。
Footer总结
MJRefreshAutoFooter 自动刷新
1. NSObject (MJRefresh) 中 [self insertSubview:mj_footer atIndex:0];
2. MJRefreshAutoFooter中 - (void)willMoveToSuperview:(UIView *)newSuperview
scrollView 的contentInset.bottom += 44; //会调用scrollViewContentSizeDidChange
AutoFooter.frame.y = scrollView.contentInset.bottom
3. scrollViewContentOffsetDidChange
先判断是否超过一屏,然后
偏移量 > (content inset.height - 屏幕高+44*1 +content inset.bottom-44
)之后调用beginRefreshing
设置state 在MJRefreshFooter的- (void)setState:中,executeRefreshingCallback。
4.MJRefreshAutoFooter 1). -scrollViewContentSizeDidChange 调用时机 reloadData 变回调用
self.mj_y=self.scrollView.mj_contentH;
MJRefreshBackFooter 需要二次刷新
实现原理: scrollViewContentOffsetDidChange 中
a = self.scrollView.mj_offsetY ;
b = self.scrollView.contentSize - self.scrollView.frame.size.height;
c = b+44 ;
1.判断state && a > c 设置为pulling状态
2.判断 self.scrollView.isDragging= NO 且state==pulling.
- (void)setState:(MJRefreshState)state 中
当为idle时,设置回contentSize.bottom
当为refreshing时,contentSize.bottom +=44;contentOffSize.y = b+44;
随后, scrollViewContentSizeDidChange中,设置footer的frame.y
MJ下载地址:
// 代码地址: https://github.com/CoderMJLee/MJRefresh
// 代码地址: http://code4app.com/ios/%E5%BF%AB%E9%80%9F%E9%9B%86%E6%88%90%E4%B8%8B%E6%8B%89%E4%B8%8A%E6%8B%89%E5%88%B7%E6%96%B0/52326ce26803fabc46000000