首页 > 代码库 > iOS开发项目篇—41cell的frame的细节处理

iOS开发项目篇—41cell的frame的细节处理

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 *)refreshControl120 {121     [self loadNewStatuses:refreshControl];122 }123 124 #pragma mark- 刷新125 -(void)refresh:(BOOL)fromSelf126 {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 *)statuses150 {151     NSMutableArray *frames = [NSMutableArray array];152     for (YYStatusModel *status in statuses) {153         YYStatusFrame *frame = [[YYStatusFrame alloc] init];154         // 传递微博模型数据,计算所有子控件的frame155         frame.status = status;156         [frames addObject:frame];157     }158     return frames;159 }160 161 -(void)loadNewStatuses:(UIRefreshControl *)refreshControl162 {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)loadMoreStatuses204 {205     //1.封装请求参数206     YYHomeStatusesParam *param=[YYHomeStatusesParam param];207     YYStatusFrame *lastStatusFrame=[self.statusesFrame lastObject];208     YYStatusModel *lastStatus=lastStatusFrame.status;209     if (lastStatus) {210         param.max_id=@([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)count239 {240     //0.清零提醒数字241     [UIApplication sharedApplication].applicationIconBadgeNumber -=self.tabBarItem.badgeValue.intValue;242     self.tabBarItem.badgeValue=http://www.mamicode.com/nil;243     244     //1.创建一个label245     UILabel *label=[[UILabel alloc]init];246     247     //2.设置label的文字248     if (count) {249         label.text=[NSString stringWithFormat:@"共有%d条新的微博数据",count];250     }else251     {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的frame261     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)setupNavBar298 {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 //    name=@"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 *)titleButton330 {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-YYPopMenuDelegate346 //弹出菜单347 -(void)popMenuDidDismissed:(YYPopMenu *)popMenu348 {349     YYTitleButton *titleButton=(YYTitleButton *)self.navigationItem.titleView;350     [titleButton setImage:[UIImage imageWithName:@"navigationbar_arrow_down"] forState:UIControlStateNormal];351 }352 -(void)pop353 {354     YYLog(@"---POP---");355 }356 -(void)friendsearch357 {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 source367 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section368 {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 *)indexPath376 {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 *)indexPath396 {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 *)scrollView406 {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.如果能看见整个footer415     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 *)indexPath428 {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 @end15 16 @implementation YYStatusCell17 18 +(instancetype)cellWithTableView:(UITableView *)tableView19 {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 *)reuseIdentifier30 {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)setupDetailView46 {47     YYStatusDetailView *detailView=[[YYStatusDetailView alloc]init];48     [self.contentView addSubview:detailView];49     self.detailView=detailView;50 }51 52 /**添加工具条*/53 -(void)setupToolbar54 {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 *)statusFrame62 {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 @end13 @implementation YYStatusDetailFrame14 15 -(void)setStatus:(YYStatusModel *)status16 {17     _status=status;18     //1.计算原创微博的frame19     [self setupStatusOriginalFrame];20     21     //2.计算转发微博的frame22     [self setupStatusRetweetedFrameWithStatus:status];23     24     //3.计算自己的frame25     [self setupDetailFrame];26     27 }28 29 /**30  *  计算原创微博的frame31  */32 -(void)setupStatusOriginalFrame33 {34     YYStatusOriginalFrame *originalFrame=[[YYStatusOriginalFrame alloc]init];35     originalFrame.status=self.status;36     self.originalFrame=originalFrame;37 }38 39 /**40  *  计算转发微博的frame41  */42 -(void)setupStatusRetweetedFrameWithStatus:(YYStatusModel *)status43 {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     }else54     {55         self.tempHeight=CGRectGetMaxY(self.originalFrame.frame);56     }57 58 }59 60 /**61  *  计算自己的frame62  */63 -(void)setupDetailFrame64 {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