iOS开发项目篇—32添加上拉刷新数据
一、简单说明
图片示意
思路:可以自定义一个view(示意xib),在view中添加一个label和菊花,指示状态。把这个view设置为tableView的底部视图。
二、实现过程
1.新建一个类和xib,关联
(1)创建一个类,让其继承自UIView
(2)创建一个xib文件,用来定义上拉提示框
(3)定义的xib文件,把类和xib文件进行关联
2.实现代码:
YYlaodStatusesFooter.h文件
1 // 2 // YYlaodStatusesFooter.h 3 // 4 5 #import <UIKit/UIKit.h> 6 7 @interface YYloadStatusesFooter : UIView 8 +(instancetype)loadFooter; 9 10 11 - (void)beginRefreshing; 12 - (void)endRefreshing; 13 14 @property (nonatomic, assign, getter = isRefreshing) BOOL refreshing; 15 @end
YYlaodStatusesFooter.m文件
1 // 2 // YYlaodStatusesFooter.m 3 // 4 5 #import "YYloadStatusesFooter.h" 6 7 @interface YYloadStatusesFooter () 8 @property (weak, nonatomic) IBOutlet UILabel *loadLabel; 9 @property (weak, nonatomic) IBOutlet UIActivityIndicatorView *loadingView; 10 @end 11 12 @implementation YYloadStatusesFooter 13 14 +(instancetype)loadFooter 15 { 16 //加载xib 17 return [[[NSBundle mainBundle] loadNibNamed:@"YYloadStatusesFooter" owner:nil options:nil] lastObject]; 18 } 19 20 - (void)beginRefreshing 21 { 22 self.loadLabel.text = @"正在拼命加载更多数据..."; 23 [self.loadingView startAnimating]; 24 self.refreshing = YES; 25 } 26 27 - (void)endRefreshing 28 { 29 self.loadLabel.text = @"上拉可以加载更多数据"; 30 [self.loadingView stopAnimating]; 31 self.refreshing = NO; 32 } 33 @end
YYHomeTableViewController.m文件
1 // 2 // YYHomeTableViewController.m 3 // 4 5 #import "YYHomeTableViewController.h" 6 #import "YYOneViewController.h" 7 #import "YYTitleButton.h" 8 #import "YYPopMenu.h" 9 #import "YYAccountModel.h" 10 #import "YYAccountTool.h" 11 #import "AFNetworking.h" 12 #import "UIImageView+WebCache.h" 13 #import "YYUserModel.h" 14 #import "YYStatusModel.h" 15 #import "MJExtension.h" 16 #import "YYloadStatusesFooter.h" 17 18 @interface YYHomeTableViewController ()<YYPopMenuDelegate> 19 @property(nonatomic,assign)BOOL down; 20 @property(nonatomic,strong)NSMutableArray *statuses; 21 @property(nonatomic,strong)YYloadStatusesFooter *footer; 22 @end 23 24 @implementation YYHomeTableViewController 25 26 #pragma mark- 懒加载 27 -(NSMutableArray *)statuses 28 { 29 if (_statuses==nil) { 30 _statuses=[NSMutableArray array]; 31 } 32 return _statuses; 33 } 34 - (void)viewDidLoad 35 { 36 [super viewDidLoad]; 37 38 //设置导航栏内容 39 [self setupNavBar]; 40 41 //集成刷新控件 42 [self setupRefresh]; 43 } 44 45 //集成刷新控件 46 -(void)setupRefresh 47 { 48 // 1.添加下拉刷新控件 49 UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; 50 [self.tableView addSubview:refreshControl]; 51 52 //2.监听状态 53 [refreshControl addTarget:self action:(@selector(refreshControlStateChange:)) forControlEvents:UIControlEventValueChanged]; 54 55 //3.让刷新控件自动进入到刷新状态 56 [refreshControl beginRefreshing]; 57 58 //4.手动调用方法,加载数据 59 //模拟网络延迟,延迟2.0秒 60 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 61 [self refreshControlStateChange:refreshControl]; 62 }); 63 64 //5.上拉刷新数据 65 YYloadStatusesFooter *footer=[YYloadStatusesFooter loadFooter]; 66 self.tableView.tableFooterView=footer; 67 self.footer=footer; 68 69 70 } 71 72 /** 73 * 当下拉刷新控件进入刷新状态(转圈圈)的时候会自动调用 74 */ 75 -(void)refreshControlStateChange:(UIRefreshControl *)refreshControl 76 { 77 //1.获得请求管理者 78 AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager]; 79 80 //2.封装请求参数 81 NSMutableDictionary *params=[NSMutableDictionary dictionary]; 82 params[@"access_token"] =[YYAccountTool accountModel].access_token; 83 //取出当前微博模型中的第一条数据,获取第一条数据的id 84 YYStatusModel *firstStatus=[self.statuses firstObject]; 85 if (firstStatus) { 86 params[@"since_id"]=firstStatus.idstr; 87 } 88 89 //3.发送Get请求 90 [mgr GET:@"https://api.weibo.com/2/statuses/home_timeline.json" parameters:params success:^(AFHTTPRequestOperation *operation, NSDictionary*accountDict) { 91 // 微博字典 -- 数组 92 NSArray *statusDictArray = accountDict[@"statuses"]; 93 //微博字典数组---》微博模型数组 94 NSArray *newStatuses =[YYStatusModel objectArrayWithKeyValuesArray:statusDictArray]; 95 96 //把新数据添加到旧数据的前面 97 NSRange range=NSMakeRange(0, newStatuses.count); 98 NSIndexSet *indexSet=[NSIndexSet indexSetWithIndexesInRange:range]; 99 [self.statuses insertObjects:newStatuses atIndexes:indexSet]; 100 YYLog(@"刷新了--%d条新数据",newStatuses.count); 101 102 //重新刷新表格 103 [self.tableView reloadData]; 104 //让刷新控件停止刷新(回复默认的状态) 105 [refreshControl endRefreshing]; 106 107 [self showNewStatusesCount:newStatuses.count]; 108 109 } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 110 YYLog(@"请求失败"); 111 //让刷新控件停止刷新(回复默认的状态) 112 [refreshControl endRefreshing]; 113 }]; 114 115 } 116 117 /** 118 * 加载更多的微博数据 119 */ 120 - (void)loadMoreStatuses 121 { 122 // 1.获得请求管理者 123 AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager]; 124 125 // 2.封装请求参数 126 NSMutableDictionary *params = [NSMutableDictionary dictionary]; 127 params[@"access_token"] = [YYAccountTool accountModel].access_token; 128 YYStatusModel *lastStatus = [self.statuses lastObject]; 129 if (lastStatus) { 130 // max_id false int64 若指定此参数,则返回ID小于或等于max_id的微博,默认为0。 131 params[@"max_id"] = @([lastStatus.idstr longLongValue] - 1); 132 } 133 134 // 3.发送GET请求 135 [mgr GET:@"https://api.weibo.com/2/statuses/home_timeline.json" parameters:params 136 success:^(AFHTTPRequestOperation *operation, NSDictionary *resultDict) { 137 // 微博字典数组 138 NSArray *statusDictArray = resultDict[@"statuses"]; 139 // 微博字典数组 ---> 微博模型数组 140 NSArray *newStatuses = [YYStatusModel objectArrayWithKeyValuesArray:statusDictArray]; 141 142 // 将新数据插入到旧数据的最后面 143 [self.statuses addObjectsFromArray:newStatuses]; 144 145 // 重新刷新表格 146 [self.tableView reloadData]; 147 148 // 让刷新控件停止刷新(恢复默认的状态) 149 [self.footer endRefreshing]; 150 } failure:^(AFHTTPRequestOperation *operation, NSError *error) { 151 YYLog(@"请求失败--%@", error); 152 // 让刷新控件停止刷新(恢复默认的状态) 153 [self.footer endRefreshing]; 154 }]; 155 } 156 157 /** 158 * 提示用户最新的微博数量 159 * 160 * @param count 最新的微博数量 161 */ 162 -(void)showNewStatusesCount:(int)count 163 { 164 //1.创建一个label 165 UILabel *label=[[UILabel alloc]init]; 166 167 //2.设置label的文字 168 if (count) { 169 label.text=[NSString stringWithFormat:@"共有%d条新的微博数据",count]; 170 }else 171 { 172 label.text=@"没有最新的微博数据"; 173 } 174 175 //3.设置label的背景和对其等属性 176 label.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageWithName:@"timeline_new_status_background"]]; 177 label.textAlignment=UITextAlignmentCenter; 178 label.textColor=[UIColor whiteColor]; 179 180 //4.设置label的frame 181 label.x=0; 182 label.width=self.view.width; 183 label.height=35; 184 // label.y=64-label.height; 185 label.y=self.navigationController.navigationBar.height+20-label.height; 186 187 //5.把lable添加到导航控制器的View上 188 // [self.navigationController.view addSubview:label]; 189 //把label添加到导航控制器上,显示在导航栏的下面 190 [self.navigationController.view insertSubview:label belowSubview:self.navigationController.navigationBar]; 191 192 //6.设置动画效果 193 CGFloat duration=0.75; 194 //设置提示条的透明度 195 label.alpha=0.0; 196 [UIView animateWithDuration:duration animations:^{ 197 //往下移动一个label的高度 198 label.transform=CGAffineTransformMakeTranslation(0, label.height); 199 label.alpha=1.0; 200 } completion:^(BOOL finished) {//向下移动完毕 201 202 //延迟delay秒的时间后,在执行动画 203 CGFloat delay=0.5; 204 205 [UIView animateKeyframesWithDuration:duration delay:delay options:UIViewAnimationOptionCurveEaseOut animations:^{ 206 207 //恢复到原来的位置 208 label.transform=CGAffineTransformIdentity; 209 label.alpha=0.0; 210 211 } completion:^(BOOL finished) { 212 213 //删除控件 214 [label removeFromSuperview]; 215 }]; 216 }]; 217 } 218 219 /** 220 UIViewAnimationOptionCurveEaseInOut = 0 << 16, // 开始:由慢到快,结束:由快到慢 221 UIViewAnimationOptionCurveEaseIn = 1 << 16, // 由慢到块 222 UIViewAnimationOptionCurveEaseOut = 2 << 16, // 由快到慢 223 UIViewAnimationOptionCurveLinear = 3 << 16, // 线性,匀速 224 */ 225 226 /**设置导航栏内容*/ 227 -(void)setupNavBar 228 { 229 self.navigationItem.leftBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_friendsearch" highImageName:@"navigationbar_friendsearch_highlighted" target:self action:@selector(friendsearch)]; 230 self.navigationItem.rightBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_pop" highImageName:@"navigationbar_pop_highlighted" target:self action:@selector(pop)]; 231 232 //设置导航栏按钮 233 YYTitleButton *titleButton=[[YYTitleButton alloc]init]; 234 //设置文字 235 [titleButton setTitle:@"首页" forState:UIControlStateNormal]; 236 //设置图标 237 [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_down"] forState:UIControlStateNormal]; 238 //设置背景 239 [titleButton setBackgroundImage:[UIImage resizedImage:@"navigationbar_filter_background_highlighted"] forState:UIControlStateHighlighted]; 240 241 //设置尺寸 242 titleButton.width=100; 243 titleButton.height=35; 244 //监听按钮的点击事件 245 [titleButton addTarget:self action:@selector(titleButtonClick:) forControlEvents:UIControlEventTouchUpInside]; 246 self.navigationItem.titleView=titleButton; 247 } 248 -(void)titleButtonClick:(UIButton *)titleButton 249 { 250 251 [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_up"] forState:UIControlStateNormal]; 252 253 UITableView *tableView=[[UITableView alloc]init]; 254 [tableView setBackgroundColor:[UIColor yellowColor]]; 255 YYPopMenu *menu=[YYPopMenu popMenuWithContentView:tableView]; 256 [menu showInRect:CGRectMake(60, 55, 200, 200)]; 257 menu.dimBackground=YES; 258 259 menu.arrowPosition=YYPopMenuArrowPositionRight; 260 menu.delegate=self; 261 } 262 263 264 #pragma mark-YYPopMenuDelegate 265 //弹出菜单 266 -(void)popMenuDidDismissed:(YYPopMenu *)popMenu 267 { 268 YYTitleButton *titleButton=(YYTitleButton *)self.navigationItem.titleView; 269 [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_down"] forState:UIControlStateNormal]; 270 } 271 -(void)pop 272 { 273 YYLog(@"---POP---"); 274 } 275 -(void)friendsearch 276 { 277 //跳转到one这个子控制器界面 278 YYOneViewController *one=[[YYOneViewController alloc]init]; 279 one.title=@"One"; 280 //拿到当前控制器 281 [self.navigationController pushViewController:one animated:YES]; 282 283 } 284 285 #pragma mark - Table view data source 286 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 287 { 288 #warning 监听tableView每次显示数据的过程 289 //在tableView显示之前,判断有没有数据,如有有数据那么就显示底部视图 290 self.footer.hidden=self.statuses.count==0; 291 return self.statuses.count; 292 } 293 294 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 295 { 296 static NSString *ID = @"cell"; 297 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 298 if (!cell) { 299 cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; 300 } 301 302 //取出这行对应的微博字典数据,转换为数据模型 303 YYStatusModel *status=self.statuses[indexPath.row]; 304 cell.textLabel.text=status.text; 305 cell.detailTextLabel.text=status.user.name; 306 NSString *imageUrlStr=status.user.profile_image_url; 307 [cell.imageView setImageWithURL:[NSURL URLWithString:imageUrlStr] placeholderImage:[UIImage imageWithName:@"avatar_default_small"]]; 308 309 return cell; 310 } 311 312 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 313 { 314 //点击cell的时候,跳到下一个界面 315 UIViewController *newVc = [[UIViewController alloc] init]; 316 newVc.view.backgroundColor = [UIColor redColor]; 317 newVc.title = @"新控制器"; 318 [self.navigationController pushViewController:newVc animated:YES]; 319 } 320 321 #pragma mark-代理方法 322 - (void)scrollViewDidScroll:(UIScrollView *)scrollView 323 { 324 if (self.statuses.count <= 0 || self.footer.isRefreshing) return; 325 326 // 1.差距 327 CGFloat delta = scrollView.contentSize.height - scrollView.contentOffset.y; 328 // 刚好能完整看到footer的高度 329 CGFloat sawFooterH = self.view.height - self.tabBarController.tabBar.height; 330 331 // 2.如果能看见整个footer 332 if (delta <= (sawFooterH - 0)) { 333 // 进入上拉刷新状态 334 [self.footer beginRefreshing]; 335 336 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 337 // 加载更多的微博数据 338 [self loadMoreStatuses]; 339 }); 340 } 341 } 342 @end
3.实现效果:
iOS开发项目篇—32添加上拉刷新数据
时间: 2024-10-27 06:42:27