空下来做了一个下拉刷新的小demo,一开始还去找代理方法,找可用控件,发现没有(也有可能是我至今未找到=。=),就自己做了一个,效果还不错,现在来给大家讲解一下。源代码使用我博客中的 “UITableView初窥 – 绑定数据源、代理、修改、全局刷新、局部刷新” 。因为要下拉操作,View必须是UIScrollView或是其子类,UITableView就是一个子类,数据啥的都有了,省的我再敲代码了。 为省时间,我能用xib的地方就用xib了。 新建一个xib,取名为reloadBar,取名随自己高兴,别纠结于此。
并拖好各控件的IBOutlet。 我这里的.h代码是这样的,大家别纠结我的命名方式啊
1 //MCViewController.h 2 3 @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *loadingActivity; 4 @property (weak, nonatomic) IBOutlet UIButton *btnArrow; 5 @property (weak, nonatomic) IBOutlet UILabel *reloadingText;
然后写实现,这里我代码全贴了,代码内部加注释,看不明白的可以博客留言
1 //MCViewController.m 2 3 //头部定义三种下拉显示的文字 4 #define RELOADINGTEXTSTYLEDEFAULT @"下拉刷新" //默认状态 5 #define RELOADINGTEXTSTYLESCROLL @"放开后刷新数据" //下拉但没有释放的状态 6 #define RELOADINGTEXTSTYLERELOADING @"刷新中" //下拉并释放的状态 7 8 //UITableViewDataSource,UITableViewDelegate,UIAlertViewDelegate 9 //是之前项目用到的协议 10 //UIScrollViewDelegate是这次用到的,因为要判断用户的拖拽 11 @interface MCViewController ()<UITableViewDataSource,UITableViewDelegate,UIAlertViewDelegate,UIScrollViewDelegate>{ 12 13 NSArray *array; //之前项目的 14 NSMutableArray *_array; //之前项目的 15 UITableView *_tableView; //之前项目的 16 17 UIView *loadView; //把loadView放到成员变量里,方便调用 18 19 BOOL willReloading; //一个BOOL值,判断是否正在reload,避免重复刷新 20 } 21 22 - (void)viewDidLoad 23 { 24 willReloading = NO; //初始化状态,默认为不会有刷新操作 25 26 /* 27 * 之前项目的代码段,主要是初始化 UITableView 并将数据模型添加到其中 28 */ 29 NSArray *nibs = [[NSBundle mainBundle]loadNibNamed:@"reloadBar" owner:self options:nil]; 30 loadView = [nibs objectAtIndex:0]; 31 // loadView = [[NSBundle mainBundle]loadNibNamed:@"reloadBar" owner:self options:nil][0]; 可以等价于上面两句 32 33 //40和-40是我假设我这个xib的高度为40,不必纠结 34 //要搞懂的地方是为什么是-40,因为一开始我们并不想看到这个bar,所以放到-40隐藏起来 35 loadView.frame = CGRectMake(0, -40, self.view.frame.size.width, 40); 36 [_tableView insertSubview:loadView atIndex:0]; 37 //_tableView就是上面说的 UITableView 38 } 39 40 // 代理方法,拖动 UITableView 会自动调用这个方法 41 // 如果不明白什么是代理方法,可以参见我的博客 “代理模式简介与实现 – delegate” 42 -(void)scrollViewDidScroll:(UIScrollView *)scrollView{ 43 // 如果刷新状态被标记了,说明程序已经要执行刷新操作了,不要再去执行任何操作 44 if (willReloading == YES) return; 45 [UIView beginAnimations:nil context:NULL]; 46 [UIView setAnimationDuration:0.3]; 47 48 // 如果用户下拉了,(下拉了那scrollView的x值是肯定小于0的)就改变状态文字 49 if(scrollView.contentOffset.y < 0){ 50 _reloadingText.text = RELOADINGTEXTSTYLEDEFAULT; 51 } 52 53 // 如果用户下拉过头了,要提醒用户松开手指进行刷新 54 if(scrollView.contentOffset.y <= -40){ 55 _reloadingText.text = RELOADINGTEXTSTYLESCROLL; 56 } 57 58 [UIView commitAnimations]; 59 } 60 61 // 代理方法,当用户结束拖拽(放开手指)时会自动调用,后面千奇百怪的参数我就不介绍了 62 // 自己看文档补补课去,我这里只用到scrollView对象 63 -(void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{ 64 // 同上,已经在操作就不要反复刷新 65 if(willReloading == YES) return; 66 67 // 需要判断用户是否决定刷新,也有的用户反悔了,不想刷新了,那他可能会拉回去一点 68 // 我们这里判断的是用户下拉的高度大于我们reloadBar的高度了,是需要刷新的 69 if(scrollView.contentOffset.y <= 40){ 70 willReloading = YES; // 标记系统会刷新操作 71 [UIView beginAnimations:nil context:NULL]; 72 [UIView setAnimationDuration:0.3]; 73 74 // 剪头调个头,往下指 75 _btnArrow.transform = CGAffineTransformMakeRotation(3.1415); 76 // 这句很重要,因为在刷新的时候我们是希望看到这个reloadBar的,而不是莫名 77 // 其妙消失了,让用户不知道到底刷新操作成功了没 78 // 所以这里我们指定scrollView的显示范围,头部增加40 79 scrollView.contentInset = UIEdgeInsetsMake(40, 0, 0, 0); 80 // 让菊花转起来 81 [_loadingActivity startAnimating]; 82 // 改变状态文字 83 _reloadingText.text = RELOADINGTEXTSTYLERELOADING; 84 [UIView commitAnimations]; 85 86 // 模拟3秒后操作 87 [self performSelector:@selector(stopLoading:) withObject:scrollView afterDelay:3]; 88 89 } 90 91 } 92 93 // 3秒后模拟的操作 94 - (void)stopLoading:(UIScrollView*)scrollView{ 95 [UIView beginAnimations:nil context:NULL]; 96 [UIView setAnimationDuration:0.3]; 97 98 // 各种控件归为原状 99 _btnArrow.transform = CGAffineTransformMakeRotation(0); 100 [_loadingActivity stopAnimating]; 101 scrollView.contentInset = UIEdgeInsetsMake(0, 0, 0, 0); 102 // 归位完毕 103 // _tableView 全局刷新 104 [_tableView reloadData]; 105 // 标记操作完毕,等待下一次操作 106 willReloading = NO; 107 108 [UIView commitAnimations]; 109 }
完整的源代码我传上来,大家可以任意下载看