iOS开发项目篇—41cell的frame的细节处理
一、简单说明
在首页控制器中使用自定义的UITableViewcell
代码如下:
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 //#import "YYHttpTool.h" 18 #import "YYHomeStatusesParam.h" 19 #import "YYHomeStatusesResult.h" 20 #import "YYStatusTool.h" 21 #import "YYUserInfoParam.h" 22 #import "YYUserTool.h" 23 #import "YYStatusFrame.h" 24 #import "YYStatusCell.h" 25 26 @interface YYHomeTableViewController ()<YYPopMenuDelegate> 27 @property(nonatomic,assign)BOOL down; 28 @property(nonatomic,strong)NSMutableArray *statusesFrame; 29 @property(nonatomic,strong)YYloadStatusesFooter *footer; 30 @property(nonatomic,strong) YYTitleButton *titleButton; 31 @property (nonatomic, weak) UIRefreshControl *refreshControl; 32 @end 33 34 @implementation YYHomeTableViewController 35 36 #pragma mark- 懒加载 37 -(NSMutableArray *)statusesFrame 38 { 39 if (_statusesFrame==nil) { 40 _statusesFrame=[NSMutableArray array]; 41 } 42 return _statusesFrame; 43 } 44 - (void)viewDidLoad 45 { 46 [super viewDidLoad]; 47 48 //设置导航栏内容 49 [self setupNavBar]; 50 51 //集成刷新控件 52 [self setupRefresh]; 53 54 //设置用户的昵称为标题 55 //先显示首页标题,延迟两秒之后变换成用户昵称 56 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 57 [self setupUserInfo]; 58 }); 59 } 60 61 /** 62 *设置用户的昵称为标题 63 */ 64 -(void)setupUserInfo 65 { 66 //1.封装请求参数 67 // YYUserInfoParam *params=[[YYUserInfoParam alloc]init]; 68 // params.access_token=[YYAccountTool accountModel].access_token; 69 YYUserInfoParam *params=[YYUserInfoParam param]; 70 params.uid=[YYAccountTool accountModel].uid; 71 72 //2.发送网络请求 73 [YYUserTool userInfoWithParam:params success:^(YYUserInfoResult *result) { 74 75 //字典转模型 76 YYUserModel *user=result; 77 78 //设置标题 79 [self.titleButton setTitle:user.name forState:UIControlStateNormal]; 80 // 存储账号信息(需要先拿到账号) 81 YYAccountModel *account=[YYAccountTool accountModel]; 82 account.name=user.name; 83 //存储 84 [YYAccountTool save:account]; 85 } failure:^(NSError *error) { 86 YYLog(@"请求失败"); 87 }]; 88 } 89 90 //集成刷新控件 91 -(void)setupRefresh 92 { 93 // 1.添加下拉刷新控件 94 UIRefreshControl *refreshControl = [[UIRefreshControl alloc] init]; 95 [self.tableView addSubview:refreshControl]; 96 self.refreshControl=refreshControl; 97 98 //2.监听状态 99 [refreshControl addTarget:self action:(@selector(refreshControlStateChange:)) forControlEvents:UIControlEventValueChanged]; 100 101 //3.让刷新控件自动进入到刷新状态 102 [refreshControl beginRefreshing]; 103 104 //4.手动调用方法,加载数据 105 //模拟网络延迟,延迟2.0秒 106 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 107 [self refreshControlStateChange:refreshControl]; 108 }); 109 110 //5.上拉刷新数据 111 YYloadStatusesFooter *footer=[YYloadStatusesFooter loadFooter]; 112 self.tableView.tableFooterView=footer; 113 self.footer=footer; 114 } 115 116 /** 117 * 当下拉刷新控件进入刷新状态(转圈圈)的时候会自动调用 118 */ 119 -(void)refreshControlStateChange:(UIRefreshControl *)refreshControl 120 { 121 [self loadNewStatuses:refreshControl]; 122 } 123 124 #pragma mark- 刷新 125 -(void)refresh:(BOOL)fromSelf 126 { 127 if (self.tabBarItem.badgeValue) {//如果有数字 128 //转圈圈 129 [self.refreshControl beginRefreshing]; 130 131 //刷新数据 132 [self loadNewStatuses:self.refreshControl]; 133 }else if(fromSelf) // 没有数字 134 { 135 //让表格回到最顶部 136 NSIndexPath *firstRow=[NSIndexPath indexPathForItem:0 inSection:0]; 137 [self.tableView scrollToRowAtIndexPath:firstRow atScrollPosition:UITableViewScrollPositionTop animated:YES]; 138 139 } 140 } 141 #pragma mark-加载微博数据 142 143 /** 144 * 根据微博模型数组 转成 微博frame模型数据 145 * 146 * @param statuses 微博模型数组 147 * 148 */ 149 - (NSArray *)statusFramesWithStatuses:(NSArray *)statuses 150 { 151 NSMutableArray *frames = [NSMutableArray array]; 152 for (YYStatusModel *status in statuses) { 153 YYStatusFrame *frame = [[YYStatusFrame alloc] init]; 154 // 传递微博模型数据,计算所有子控件的frame 155 frame.status = status; 156 [frames addObject:frame]; 157 } 158 return frames; 159 } 160 161 -(void)loadNewStatuses:(UIRefreshControl *)refreshControl 162 { 163 //1.封装请求参数 164 // YYHomeStatusesParam *param=[[YYHomeStatusesParam alloc]init]; 165 // param.access_token=[YYAccountTool accountModel].access_token; 166 YYHomeStatusesParam *param=[YYHomeStatusesParam param]; 167 YYStatusFrame *firstStatusFrame=[self.statusesFrame firstObject]; 168 YYStatusModel *firstStatus=firstStatusFrame.status; 169 if (firstStatus) { 170 param.since_id=@([firstStatus.idstr longLongValue]); 171 } 172 173 //2.加载微博数据 174 [YYStatusTool homeStatusesWithParam:param success:^(YYHomeStatusesResult *result) { 175 //获取最新的微博数组 176 // NSArray *newStatuses=result.statuses; 177 NSArray *newFrames=[self statusFramesWithStatuses:result.statuses]; 178 179 //把新数据添加到旧数据的前面 180 NSRange range=NSMakeRange(0, newFrames.count); 181 NSIndexSet *indexSet=[NSIndexSet indexSetWithIndexesInRange:range]; 182 [self.statusesFrame insertObjects:newFrames atIndexes:indexSet]; 183 YYLog(@"刷新了--%d条新数据",newFrames.count); 184 185 //重新刷新表格 186 [self.tableView reloadData]; 187 //让刷新控件停止刷新(回复默认的状态) 188 [refreshControl endRefreshing]; 189 [self showNewStatusesCount:newFrames.count]; 190 191 } failure:^(NSError *error) { 192 YYLog(@"请求失败"); 193 //让刷新控件停止刷新(回复默认的状态) 194 [refreshControl endRefreshing]; 195 196 }]; 197 198 } 199 200 /** 201 * 加载更多的微博数据 202 */ 203 - (void)loadMoreStatuses 204 { 205 //1.封装请求参数 206 YYHomeStatusesParam *param=[YYHomeStatusesParam param]; 207 YYStatusFrame *lastStatusFrame=[self.statusesFrame lastObject]; 208 YYStatusModel *lastStatus=lastStatusFrame.status; 209 if (lastStatus) { 210 [email protected]([lastStatus.idstr longLongValue]-1); 211 } 212 213 //2.发送网络请求 214 [YYStatusTool homeStatusesWithParam:param success:^(YYHomeStatusesResult *result) { 215 216 //获取最新的微博数组 217 // NSArray *newStatuses=result.statuses; 218 NSArray *newFrames=[self statusFramesWithStatuses:result.statuses]; 219 220 // 将新数据插入到旧数据的最后面 221 [self.statusesFrame addObjectsFromArray:newFrames]; 222 // 重新刷新表格 223 [self.tableView reloadData]; 224 // 让刷新控件停止刷新(恢复默认的状态) 225 [self.footer endRefreshing]; 226 } failure:^(NSError *error) { 227 YYLog(@"请求失败--%@", error); 228 // 让刷新控件停止刷新(恢复默认的状态) 229 [self.footer endRefreshing]; 230 }]; 231 } 232 233 /** 234 * 提示用户最新的微博数量 235 * 236 * @param count 最新的微博数量 237 */ 238 -(void)showNewStatusesCount:(int)count 239 { 240 //0.清零提醒数字 241 [UIApplication sharedApplication].applicationIconBadgeNumber -=self.tabBarItem.badgeValue.intValue; 242 self.tabBarItem.badgeValue=nil; 243 244 //1.创建一个label 245 UILabel *label=[[UILabel alloc]init]; 246 247 //2.设置label的文字 248 if (count) { 249 label.text=[NSString stringWithFormat:@"共有%d条新的微博数据",count]; 250 }else 251 { 252 label.text=@"没有最新的微博数据"; 253 } 254 255 //3.设置label的背景和对其等属性 256 label.backgroundColor=[UIColor colorWithPatternImage:[UIImage imageWithName:@"timeline_new_status_background"]]; 257 label.textAlignment=UITextAlignmentCenter; 258 label.textColor=[UIColor whiteColor]; 259 260 //4.设置label的frame 261 label.x=0; 262 label.width=self.view.width; 263 label.height=35; 264 label.y=self.navigationController.navigationBar.height+20-label.height; 265 266 //5.把lable添加到导航控制器的View上 267 [self.navigationController.view insertSubview:label belowSubview:self.navigationController.navigationBar]; 268 269 //6.设置动画效果 270 CGFloat duration=0.75; 271 //设置提示条的透明度 272 label.alpha=0.0; 273 [UIView animateWithDuration:duration animations:^{ 274 //往下移动一个label的高度 275 label.transform=CGAffineTransformMakeTranslation(0, label.height); 276 label.alpha=1.0; 277 } completion:^(BOOL finished) {//向下移动完毕 278 279 //延迟delay秒的时间后,在执行动画 280 CGFloat delay=0.5; 281 282 [UIView animateKeyframesWithDuration:duration delay:delay options:UIViewAnimationOptionCurveEaseOut animations:^{ 283 284 //恢复到原来的位置 285 label.transform=CGAffineTransformIdentity; 286 label.alpha=0.0; 287 288 } completion:^(BOOL finished) { 289 290 //删除控件 291 [label removeFromSuperview]; 292 }]; 293 }]; 294 } 295 296 /**设置导航栏内容*/ 297 -(void)setupNavBar 298 { 299 self.navigationItem.leftBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_friendsearch" highImageName:@"navigationbar_friendsearch_highlighted" target:self action:@selector(friendsearch)]; 300 self.navigationItem.rightBarButtonItem=[UIBarButtonItem itemWithImageName:@"navigationbar_pop" highImageName:@"navigationbar_pop_highlighted" target:self action:@selector(pop)]; 301 302 //设置导航栏按钮 303 YYTitleButton *titleButton=[[YYTitleButton alloc]init]; 304 305 //设置尺寸 306 titleButton.height=35; 307 308 //设置文字 309 YYAccountModel *account= [YYAccountTool accountModel]; 310 NSString *name=account.name; 311 NSLog(@"%@",name); 312 // [email protected]"yangye"; 313 //判断:如果name有值(上一次登录的用户名),那么就使用上次的,如果没有那么就设置为首页 314 if (name) { 315 [titleButton setTitle:name forState:UIControlStateNormal]; 316 }else{ 317 [titleButton setTitle:@"首页" forState:UIControlStateNormal]; 318 } 319 //设置图标 320 [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_down"] forState:UIControlStateNormal]; 321 //设置背景 322 [titleButton setBackgroundImage:[UIImage resizedImage:@"navigationbar_filter_background_highlighted"] forState:UIControlStateHighlighted]; 323 324 //监听按钮的点击事件 325 [titleButton addTarget:self action:@selector(titleButtonClick:) forControlEvents:UIControlEventTouchUpInside]; 326 self.navigationItem.titleView=titleButton; 327 self.titleButton=titleButton; 328 } 329 -(void)titleButtonClick:(UIButton *)titleButton 330 { 331 332 [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_up"] forState:UIControlStateNormal]; 333 334 UITableView *tableView=[[UITableView alloc]init]; 335 [tableView setBackgroundColor:[UIColor yellowColor]]; 336 YYPopMenu *menu=[YYPopMenu popMenuWithContentView:tableView]; 337 [menu showInRect:CGRectMake(60, 55, 200, 200)]; 338 menu.dimBackground=YES; 339 340 menu.arrowPosition=YYPopMenuArrowPositionRight; 341 menu.delegate=self; 342 } 343 344 345 #pragma mark-YYPopMenuDelegate 346 //弹出菜单 347 -(void)popMenuDidDismissed:(YYPopMenu *)popMenu 348 { 349 YYTitleButton *titleButton=(YYTitleButton *)self.navigationItem.titleView; 350 [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_down"] forState:UIControlStateNormal]; 351 } 352 -(void)pop 353 { 354 YYLog(@"---POP---"); 355 } 356 -(void)friendsearch 357 { 358 //跳转到one这个子控制器界面 359 YYOneViewController *one=[[YYOneViewController alloc]init]; 360 one.title=@"One"; 361 //拿到当前控制器 362 [self.navigationController pushViewController:one animated:YES]; 363 364 } 365 366 #pragma mark - Table view data source 367 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 368 { 369 #warning 监听tableView每次显示数据的过程 370 //在tableView显示之前,判断有没有数据,如有有数据那么就显示底部视图 371 self.footer.hidden=self.statusesFrame.count==0; 372 return self.statusesFrame.count; 373 } 374 375 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 376 { 377 // static NSString *ID = @"cell"; 378 // UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 379 // if (!cell) { 380 // cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; 381 // } 382 // 383 // //取出这行对应的微博字典数据,转换为数据模型 384 // YYStatusModel *status=self.statuses[indexPath.row]; 385 // cell.textLabel.text=status.text; 386 // cell.detailTextLabel.text=status.user.name; 387 // NSString *imageUrlStr=status.user.profile_image_url; 388 // [cell.imageView setImageWithURL:[NSURL URLWithString:imageUrlStr] placeholderImage:[UIImage imageWithName:@"avatar_default_small"]]; 389 390 YYStatusCell *cell=[YYStatusCell cellWithTableView:tableView]; 391 cell.statusFrame=self.statusesFrame[indexPath.row]; 392 return cell; 393 } 394 395 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 396 { 397 //点击cell的时候,跳到下一个界面 398 UIViewController *newVc = [[UIViewController alloc] init]; 399 newVc.view.backgroundColor = [UIColor redColor]; 400 newVc.title = @"新控制器"; 401 [self.navigationController pushViewController:newVc animated:YES]; 402 } 403 404 #pragma mark-代理方法 405 - (void)scrollViewDidScroll:(UIScrollView *)scrollView 406 { 407 if (self.statusesFrame.count <= 0 || self.footer.isRefreshing) return; 408 409 // 1.差距 410 CGFloat delta = scrollView.contentSize.height - scrollView.contentOffset.y; 411 // 刚好能完整看到footer的高度 412 CGFloat sawFooterH = self.view.height - self.tabBarController.tabBar.height; 413 414 // 2.如果能看见整个footer 415 if (delta <= (sawFooterH - 0)) { 416 // 进入上拉刷新状态 417 [self.footer beginRefreshing]; 418 419 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 420 // 加载更多的微博数据 421 [self loadMoreStatuses]; 422 }); 423 } 424 } 425 426 #pragma mark-返回cell的高度 427 -(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 428 { 429 //取出对应的模型 430 YYStatusFrame *statusFrame=self.statusesFrame[indexPath.row]; 431 return statusFrame.cellHight; 432 } 433 @end
在自定义cell类中提供一个方法:
1 // 2 // YYStatusCell.h 3 // 4 5 #import <UIKit/UIKit.h> 6 @class YYStatusFrame; 7 @interface YYStatusCell : UITableViewCell 8 #warning 注意这里不能直接使用frame作为属性名。继承自UIview,而它本身就有一个frame。 9 @property(nonatomic,strong)YYStatusFrame *statusFrame; 10 11 //类方法,提供cell的初始化 12 +(instancetype)cellWithTableView:(UITableView *)tableView; 13 @end
YYStatusCell.m文件
1 // 2 // YYStatusCell.m 3 // 自定义cell 4 5 #import "YYStatusCell.h" 6 #import "YYStatusDetailView.h" 7 #import "YYStatusToolbar.h" 8 //#import "YYStatusDetailFrame.h" 9 #import "YYStatusFrame.h" 10 11 @interface YYStatusCell () 12 @property(nonatomic,weak)YYStatusDetailView *detailView; 13 @property(nonatomic,weak)YYStatusToolbar *toolbar; 14 @end 15 16 @implementation YYStatusCell 17 18 +(instancetype)cellWithTableView:(UITableView *)tableView 19 { 20 static NSString *ID = @"cell"; 21 YYStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID]; 22 if (!cell) { 23 cell = [[YYStatusCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID]; 24 } 25 return cell; 26 } 27 28 29 - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 30 { 31 self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 32 if (self) { 33 //初始化子控件 34 35 //1.添加微博具体内容 36 [self setupDetailView]; 37 38 //2.添加工具条 39 [self setupToolbar]; 40 } 41 return self; 42 } 43 44 /**添加微博具体内容*/ 45 -(void)setupDetailView 46 { 47 YYStatusDetailView *detailView=[[YYStatusDetailView alloc]init]; 48 [self.contentView addSubview:detailView]; 49 self.detailView=detailView; 50 } 51 52 /**添加工具条*/ 53 -(void)setupToolbar 54 { 55 YYStatusToolbar *toolbar=[[YYStatusToolbar alloc]init]; 56 toolbar.backgroundColor=[UIColor grayColor]; 57 [self.contentView addSubview:toolbar]; 58 self.toolbar=toolbar; 59 } 60 61 -(void)setStatusFrame:(YYStatusFrame *)statusFrame 62 { 63 _statusFrame=statusFrame; 64 //1.微博具体内容的frame数据 65 self.detailView.detailFrame=statusFrame.StatusDetailFrame; 66 67 //2.底部工具条的frame数据 68 self.toolbar.frame=statusFrame.toolbarFrame; 69 } 70 @end
二、细节处理
1.上述代码运行后的效果
出现这种情况可能的原因:
(1)frame计算出现错误
(2)没有给有文字显示的地方为文字设置字体大小
(3)正文等需要换行的地方,没有设置多行显示。
(4)在UItableView的方法中,没有返回cell的高度
1 //2.昵称 2 UILabel *nameLabel=[[UILabel alloc]init]; 3 nameLabel.font=YYStatusOrginalNameFont; 4 [self addSubview:nameLabel]; 5 self.nameLabel=nameLabel; 6 7 //3.正文 8 UILabel *textLabel=[[UILabel alloc]init]; 9 textLabel.font=YYStatusOrginalTextFont; 10 textLabel.numberOfLines=0; 11 [self addSubview:textLabel]; 12 self.textLabel=textLabel;
调整后显示效果:
先把微博来源注释掉,调整bug后的最终显示效果:
补充代码:
YYStatusDetailFrame.m文件
1 // 2 // YYStatusDetailFrame.m 3 // 4 5 #import "YYStatusDetailFrame.h" 6 #import "YYStatusOriginalFrame.h" 7 #import "YYStatusRetweetedFrame.h" 8 #import "YYStatusModel.h" 9 10 @interface YYStatusDetailFrame () 11 @property(nonatomic,assign)CGFloat tempHeight; 12 @end 13 @implementation YYStatusDetailFrame 14 15 -(void)setStatus:(YYStatusModel *)status 16 { 17 _status=status; 18 //1.计算原创微博的frame 19 [self setupStatusOriginalFrame]; 20 21 //2.计算转发微博的frame 22 [self setupStatusRetweetedFrameWithStatus:status]; 23 24 //3.计算自己的frame 25 [self setupDetailFrame]; 26 27 } 28 29 /** 30 * 计算原创微博的frame 31 */ 32 -(void)setupStatusOriginalFrame 33 { 34 YYStatusOriginalFrame *originalFrame=[[YYStatusOriginalFrame alloc]init]; 35 originalFrame.status=self.status; 36 self.originalFrame=originalFrame; 37 } 38 39 /** 40 * 计算转发微博的frame 41 */ 42 -(void)setupStatusRetweetedFrameWithStatus:(YYStatusModel *)status 43 { 44 if (status.retweeted_status) { 45 YYStatusRetweetedFrame *retweetedFrame=[[YYStatusRetweetedFrame alloc]init]; 46 retweetedFrame.retweeted_status=status.retweeted_status; 47 self.retweetedFrame=retweetedFrame; 48 49 CGRect f=retweetedFrame.frame; 50 f.origin.y=CGRectGetMaxY(self.originalFrame.frame); 51 retweetedFrame.frame=f; 52 self.tempHeight=CGRectGetMaxY(self.retweetedFrame.frame); 53 }else 54 { 55 self.tempHeight=CGRectGetMaxY(self.originalFrame.frame); 56 } 57 58 } 59 60 /** 61 * 计算自己的frame 62 */ 63 -(void)setupDetailFrame 64 { 65 CGFloat x=0; 66 CGFloat y=0; 67 CGFloat w=YYScreenW; 68 CGFloat h=self.tempHeight; 69 self.frame=CGRectMake(x, y, w, h); 70 } 71 @end
iOS开发项目篇—41cell的frame的细节处理
时间: 2024-09-29 16:42:38