没看MJRefresh源码前,自己尝试书写了UIScrollView(UITableView, UICollectionView)上拉,下拉刷新的功能,按照使用MJRefresh使用习惯,猜测实现的原理,然后写了3个类,简陋实现了的refresh(不可取,仅作学习参考)。
1,UITableView的分类
实现的思路,获取UITableVIew的代理,通过代理方法调用再次调用相应的自定义函数
获取代理
- (void)setTbHeader:(TBHeader *)tbHeader {
// 设置对象
tbHeader.tableView = self;
_tbHeader = tbHeader;
// 设置代理
self.delegate = self;
// 设置VC
_viewController = [self findViewController:self];
}
代理调用自定义的方法,如:
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
// 执行头部代理
if ([_tbHeader respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]) {
[_tbHeader scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
}
// 执行尾部代理
if ([_tbFooter respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]) {
[_tbFooter scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
}
// 执行vc代理
if ([_viewController respondsToSelector:@selector(scrollViewDidEndDragging:willDecelerate:)]) {
[(UITableViewController *)_viewController scrollViewDidEndDragging:scrollView willDecelerate:decelerate];
}
}
2,头部类TBHeader
实现思路,获取代理调用的contentoffset设置刷新状态
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
// 下拉伸进入刷新模式
if (scrollView.contentOffset.y < -scrollView.contentInset.top - pullToRefreshHeight && !self.isFreshing) {
// 开启刷新
[self headerBeginRefresh];
// 正在刷新
dispatch_async(dispatch_get_main_queue(), ^{
// NSLog(@"*****禁止惯性滚动*************Start reFresh**************************");
[scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, -scrollView.contentInset.top - refreshHeaderHeight) animated:YES];
});
}
// 解决下拉正在刷新
else if(scrollView.contentOffset.y < - scrollView.contentInset.top - pullToRefreshHeight && self.isFreshing){
// 正在刷新
dispatch_async(dispatch_get_main_queue(), ^{
// NSLog(@"*****禁止惯性滚动*************Start reFresh**************************");
[scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, -scrollView.contentInset.top - refreshHeaderHeight) animated:YES];
});
}
// 上拉刷新
else if (self.tableView.contentOffset.y + [UIScreen mainScreen].bounds.size.height >= self.tableView.contentSize.height + pullToRefreshHeight) {
}
NSLog(@"%@", NSStringFromCGPoint(self.tableView.contentOffset));
}
在原来的表格HeaderView再添加刷新UIView(后来发现不可取)
- (void)replaceNewHeader {
if (self.NewheaderViewTemp != self.tableView.tableHeaderView || !self.NewheaderViewTemp) {
UIView *NewheaderViewTemp = [[UIView alloc] init];
NewheaderViewTemp.backgroundColor = [UIColor colorWithWhite:0.5 alpha:1.0];
self.NewheaderViewTemp = NewheaderViewTemp;
UIView *headerViewOriginal = self.tableView.tableHeaderView;
NSLog(@"%@", headerViewOriginal);
self.tableView.tableHeaderView = nil;
UIButton *headerBtnView = [UIButton buttonWithType:UIButtonTypeCustom];
headerBtnView.backgroundColor = [UIColor purpleColor];
headerBtnView.titleLabel.textAlignment = NSTextAlignmentCenter;
[headerBtnView setTitle:@"下拉刷新" forState:UIControlStateNormal];
[headerBtnView addTarget:self action:@selector(headerBeginRefresh) forControlEvents:UIControlEventTouchUpInside];
self.headerBtnView = headerBtnView;
headerBtnView.frame = CGRectMake(0, 0, self.tableView.width, refreshHeaderHeight);
headerViewOriginal.y = headerBtnView.height;
[NewheaderViewTemp addSubview:headerBtnView];
// [headerViewOriginal removeFromSuperview];
NewheaderViewTemp.height = headerViewOriginal.height + headerBtnView.height;
[NewheaderViewTemp addSubview:headerViewOriginal];
self.tableView.tableHeaderView = NewheaderViewTemp;
// 重新设置inset
[self.tableView setContentInset:UIEdgeInsetsMake(self.tableView.contentInset.top - headerBtnView.height, 0, self.tableView.contentInset.bottom, 0)];
}
}
3,尾部类TBFooter
实现思路和Header相似
根据contentOffset设置状态加载更多
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
// 上拉刷新
if (self.tableView.contentOffset.y + self.tableView.height - self.tableView.contentInset.bottom >= self.tableView.contentSize.height + pullToRefreshHeight && !self.isFreshing) {
[self footerBeginRefresh];
}
NSLog(@"%@", NSStringFromCGPoint(self.tableView.contentOffset));
}
总结
1, 功能虽然是实现了,但是存在很多不足之处。
2,改变了UISrollView的真正代理对象。
3,改变了HeadView和FooterView,相应地改变了contentInset
4,可能会中断开发者UISrollView 代理方法。
自己尝试写了一遍,发现和源码MJRefresh对比之后自己的不足之处,才能领会他人的精粹,方能不断进步
附上自己尝试写的表格刷新代码(不可取,只是为了学习参考)!
https://github.com/tangbin583085/TBScrollViewRefresh