本文主要是介绍iOS UITableView下拉刷新上拉加载更多EGOTableViewPullRefresh类库使用初级剑侠篇(欢迎提建议和分享遇到的问题),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
这篇文章说下:MJRefresh和 EGOTableViewPullRefresh 的使用方法最下面有原理说明,若有不对或者建议请评论指出,先谢谢了:
首先是英文原文和类库下载地址:https://github.com/emreberge/EGOTableViewPullRefresh
然后创建好自己使用的tableview控件接着:
- 添加 QuartzCore.framework 到你的工程中。
- 将 EGOTableViewPullRefresh 拖到你的工程目录下。
下拉是一个刷新的工作,所以需要我们添加的代码无非就是数据刷新的代码。
(1)在.h文件中添加如下代码
- @interface ...ViewController : UITableViewController<EGORefreshTableHeaderDelegate>
- {
- EGORefreshTableHeaderView *refreshTableHeaderView;
- BOOL reloading;
- }
- - (void)reloadTableViewDataSource;
- - (void)doneLoadingTableViewData;
(2)在- (void)viewDidLoad函数中添加下面的代码。
- if (refreshTableHeaderView == nil) {
- <span style="white-space:pre"> </span>EGORefreshTableHeaderView *view = [[EGORefreshTableHeaderView alloc] initWithFrame:CGRectMake(0.0f, 0.0f - self.tableView.bounds.size.height, self.view.frame.size.width, self.tableView.bounds.size.height)];
- view.delegate = self;
- [self.tableView addSubview:view];
- refreshTableHeaderView = view;
- [view release];
- }
- //最后一次更新的时间
- [refreshTableHeaderView refreshLastUpdatedDate];
(3)在对应的.m文件中添加如下方法
- #pragma mark -
- #pragma mark Data Source Loading / Reloading Methods
- //更新列表数据
- - (void)reloadTableViewDataSource{
- [NSThread detachNewThreadSelector:@selector(updateNewsByPullTable) toTarget:self withObject:nil]; //异步加载数据,不影tableView动作
- reloading = YES;
- }
- //调用JSON服务获取数据
- - (void)updateNewsByPullTable
- {
- NSString *str = @"http://....../getAllNews.aspx";
- NSURL *url = [NSURL URLWithString:str];
- ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
- [request startSynchronous];
- //接收返回数据
- NSString *response = [request responseString];
- NSLog(@"%@",response);
- self.data = [response JSONValue];
- [self.tableView reloadData];
- }
- - (void)doneLoadingTableViewData{
- //model should call this when its done loading
- reloading = NO;
- [refreshTableHeaderView egoRefreshScrollViewDataSourceDidFinishedLoading:self.tableView];
- }
- #pragma mark -
- #pragma mark UIScrollViewDelegate Methods
- - (void)scrollViewDidScroll:(UIScrollView *)scrollView{
- [refreshTableHeaderView egoRefreshScrollViewDidScroll:scrollView];
- }
- - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
- [refreshTableHeaderView egoRefreshScrollViewDidEndDragging:scrollView];
- }
- #pragma mark -
- #pragma mark EGORefreshTableHeaderDelegate Methods
- - (void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView*)view{
- [self reloadTableViewDataSource];
- [self performSelector:@selector(doneLoadingTableViewData) withObject:nil afterDelay:3.0];
- }
- - (BOOL)egoRefreshTableHeaderDataSourceIsLoading:(EGORefreshTableHeaderView*)view{
- return reloading; // should return if data source model is reloading
- }
- - (NSDate*)egoRefreshTableHeaderDataSourceLastUpdated:(EGORefreshTableHeaderView*)view{
- return [NSDate date]; // should return date data source was last changed
- }
总的来说,实现这一功能并不复杂,关键在于-(void)reloadTableViewDataSource这一方法。这里我试了一下,读取数据的操作必须是异步的,要不然和tableView下拉再上弹这个动作会有很明显的延迟。再一次感受到了开源类库的强大,感谢这些大神们的无私贡献,让我们这些iOS开发初学者有机会能做出漂亮的应用。
.h
static NSString *CELL_ID = @"cell_id";
@class BaseTableView;
@protocol BaseTableViewDelegate <NSObject>
@optional
//下拉事件
- (void)pullDown:(BaseTableView *)tableView;
//上拉事件
- (void)pullUp:(BaseTableView *)tableView;
//选中单元格事件
- (void)didSelectRowAtIndexPath:(BaseTableView *)tabelView indexPath:(NSIndexPath *)indexPath;
@end
typedefvoid(^PullDonwFinish)(void);
typedefvoid(^PullUpFinish)(void);
@interface BaseTableView :UITableView<EGORefreshTableHeaderDelegate,UITableViewDataSource, UITableViewDelegate>
{
EGORefreshTableHeaderView *_refreshHeaderView;
BOOL _reloading;
UIButton *_moreButton;
}
@property(nonatomic,retain) NSMutableArray *data;
//是否显示下拉控件
@property(nonatomic,assign)BOOL refreshHeader;
//是否有更多(下一页)
@property(nonatomic,assign)BOOL isMore;
@property(nonatomic,copy)PullDonwFinish finishBlock;
@property(nonatomic,copy)PullUpFinish pullUpBlock;
//上拉代理对象
@property(nonatomic,assign)id<BaseTableViewDelegate> refreshDelegate;
//自动执行下拉动作
-(void)launchRefreshing;
- (void)reloadTableViewDataSource;
- (void)doneLoadingTableViewData;
@end
- (id)initWithFrame:(CGRect)frame
{
self = [superinitWithFrame:frame];
if (self) {
// Initialization code
[self_initViews];
}
return self;
}
- (void)awakeFromNib {
[superawakeFromNib];
[self_initViews];
}
- (void)_initViews {
self.backgroundColor =RGB(242, 243, 240);
self.refreshHeader =YES;
self.isMore =YES;
self.delegate =self;
self.dataSource =self;
_moreButton = [UIButtonbuttonWithType:UIButtonTypeCustom];
_moreButton.frame =CGRectMake(0,0, self.width,44);
_moreButton.backgroundColor = [UIColorclearColor];
[_moreButtonsetTitle:@""forState:UIControlStateNormal];
_moreButton.titleLabel.font = [UIFontsystemFontOfSize:12.0f];
[_moreButtonsetTitleColor:[UIColorlightGrayColor] forState:UIControlStateNormal];
[_moreButtonaddTarget:selfaction:@selector(loadMoreAction)forControlEvents:UIControlEventTouchUpInside];
UIActivityIndicatorView *activityView = [[UIActivityIndicatorViewalloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityView.frame =CGRectMake(90,10, 20, 20);
[activityViewstopAnimating];
activityView.tag =2013;
[_moreButtonaddSubview:activityView];
self.tableFooterView =_moreButton;
}
-(void)launchRefreshing
{
if (_reloading) {
_reloading = NO;
[UIViewanimateWithDuration:0.4animations:^{
[selfsetContentOffset:CGPointMake(0, -80)];
}completion:^(BOOL finished) {
if (finished) {
//设置停止拖拽
[_refreshHeaderViewperformSelector:@selector(egoRefreshScrollViewDidEndDragging:)withObject:selfafterDelay:0.2];
}
}];
}else{
//下拉之前还原_refreshHeaderView的state
[_refreshHeaderViewsetState:EGOOPullRefreshNormal];
[UIViewanimateWithDuration:0.4animations:^{
[selfsetContentOffset:CGPointMake(0, -80)];
}completion:^(BOOL finished) {
if (finished) {
[_refreshHeaderViewsetState:EGOOPullRefreshPulling];
//设置停止拖拽
[_refreshHeaderViewperformSelector:@selector(egoRefreshScrollViewDidEndDragging:)withObject:selfafterDelay:0.2];
}
}];
}
}
- (void)setRefreshHeader:(BOOL)refreshHeader {
_refreshHeader = refreshHeader;
if (self.refreshHeader) {
if (_refreshHeaderView ==nil) {
//创建下拉控件
_refreshHeaderView = [[EGORefreshTableHeaderViewalloc] initWithFrame:CGRectMake(0.0f,0.0f - self.bounds.size.height,self.frame.size.width,self.bounds.size.height)];
_refreshHeaderView.delegate =self;
_refreshHeaderView.backgroundColor = [UIColorclearColor];
[_refreshHeaderViewrefreshLastUpdatedDate];
}
[selfaddSubview:_refreshHeaderView];
}else {
if (_refreshHeaderView.superview !=nil) {
[_refreshHeaderViewremoveFromSuperview];
}
}
}
//上拉按钮的点击事件
- (void)loadMoreAction {
if (self.pullUpBlock !=nil) {
self.pullUpBlock();
}
//调用代理对象的协议方法
if ([self.refreshDelegaterespondsToSelector:@selector(pullUp:)]) {
[self.refreshDelegatepullUp:self];
}
[_moreButtonsetTitle:@"正在加载..."forState:UIControlStateNormal];
UIActivityIndicatorView *activityView = (UIActivityIndicatorView *)[_moreButtonviewWithTag:2013];
[activityViewstartAnimating];
}
- (void)setIsMore:(BOOL)isMore {
_isMore = isMore;
if (self.isMore) {
[_moreButtonsetTitle:@"加载更多数据"forState:UIControlStateNormal];
_moreButton.enabled =YES;
}else {
[_moreButtonsetTitle:@"没有更多数据"forState:UIControlStateNormal];
_moreButton.enabled =NO;
}
UIActivityIndicatorView *activityView = (UIActivityIndicatorView *)[_moreButtonviewWithTag:2013];
[activityViewstopAnimating];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView deselectRowAtIndexPath:indexPathanimated:YES];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.data.count;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableViewdequeueReusableCellWithIdentifier:CELL_ID];
if (!cell) {
cell = [[UITableViewCellalloc] initWithStyle:UITableViewCellStyleDefaultreuseIdentifier:CELL_ID];
}
return cell;
}
/*________________________下拉控件相关方法________________________________*/
#pragma mark -
#pragma mark Data Source Loading / Reloading Methods
- (void)reloadTableViewDataSource{
_reloading = YES;
}
//收起下拉刷新
- (void)doneLoadingTableViewData{
_reloading = NO;
[_refreshHeaderViewegoRefreshScrollViewDataSourceDidFinishedLoading:self];
}
#pragma mark -
#pragma mark UIScrollViewDelegate Methods
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
[_refreshHeaderViewegoRefreshScrollViewDidScroll:scrollView];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{
[_refreshHeaderViewegoRefreshScrollViewDidEndDragging:scrollView];
//偏移量.y + tableView.height =内容的高度
//h是上拉超出来的尺寸
float h = scrollView.contentOffset.y + scrollView.height - scrollView.contentSize.height;
if (h > 30 &&self.isMore) {
[selfloadMoreAction];
}
}
#pragma mark -
#pragma mark EGORefreshTableHeaderDelegate Methods
//下拉到一定距离,手指放开时调用
- (void)egoRefreshTableHeaderDidTriggerRefresh:(EGORefreshTableHeaderView*)view{
[selfreloadTableViewDataSource];
//停止加载,弹回下拉
// [self performSelector:@selector(doneLoadingTableViewData)
// withObject:nil afterDelay:3.0];
if (self.finishBlock !=nil) {
self.finishBlock();
}
if ([self.refreshDelegaterespondsToSelector:@selector(pullDown:)]) {
[self.refreshDelegatepullDown:self];
}
}
- (BOOL)egoRefreshTableHeaderDataSourceIsLoading:(EGORefreshTableHeaderView*)view{
return_reloading;// should return if data source model is reloading
}
//取得下拉刷新的时间
- (NSDate *)egoRefreshTableHeaderDataSourceLastUpdated:(EGORefreshTableHeaderView*)view{
return [NSDatedate]; // should return date data source was last changed
}
@end
浅谈下拉刷新和上拉加载更多原理:
下文出自: http://blog.csdn.net/hmt20130412/article/details/32695305
很多App中,新闻或者展示类都存在下拉刷新和上拉加载的效果,网上提供了实现这种效果的第三方类(详情请见MJRefresh和 EGOTableViewPullRefresh ),用起来很方便,但是闲暇之余,我们可以思考下,这种效果实现的原理是什么,我以前说过,只要是动画都是骗人的,只要不是硬件问题大部分效果都能在系统UI的基础上做出来.
@下面是关键代码分析:
// 下拉刷新的原理
- (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView
{if (scrollView.contentOffset.y < - 100) {
[UIView animateWithDuration:1.0 animations:^{
// frame发生偏移,距离顶部150的距离(可自行设定)
self.tableView.contentInset = UIEdgeInsetsMake(150.0f, 0.0f, 0.0f, 0.0f);
} completion:^(BOOL finished) {
/**
* 发起网络请求,请求刷新数据
*/ }];}
}// 上拉加载的原理
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
{NSLog(@"%f",scrollView.contentOffset.y);NSLog(@"%f",scrollView.frame.size.height);NSLog(@"%f",scrollView.contentSize.height);/*** 关键-->* scrollView一开始并不存在偏移量,但是会设定contentSize的大小,所以contentSize.height永远都会比contentOffset.y高一个手机屏幕的* 高度;上拉加载的效果就是每次滑动到底部时,再往上拉的时候请求更多,那个时候产生的偏移量,就能让contentOffset.y + 手机屏幕尺寸高大于这* 个滚动视图的contentSize.height*/if (scrollView.contentOffset.y + scrollView.frame.size.height >= scrollView.contentSize.height) {
NSLog(@"%d %s",__LINE__,__FUNCTION__);
[UIView commitAnimations];
[UIView animateWithDuration:1.0 animations:^{
// frame发生的偏移量,距离底部往上提高60(可自行设定)
self.tableView.contentInset = UIEdgeInsetsMake(0, 0, 60, 0);
} completion:^(BOOL finished) {
/**
* 发起网络请求,请求加载更多数据
* 然后在数据请求回来的时候,将contentInset改为(0,0,0,0)
*/
}];}
}
这篇关于iOS UITableView下拉刷新上拉加载更多EGOTableViewPullRefresh类库使用初级剑侠篇(欢迎提建议和分享遇到的问题)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!