05---MVC模式下动态调整Cell高度三部曲
动态调整Cell高度三部曲
我们在做项目开发的过程中经常会遇到每一个cell的高度及cell的子控件的显示个数不同,以我最近开发的微格为例,讲解一下MVC模式动态的调整Cell宽高的三部曲
1>.自定义Cell,重写- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier方法 在此方法中添加所有的可能显示的子控件
子控件的frame通过构建的cellFrame模型进行设置 - (void)setCellFrame:(cellFrame *)cellFrame (顺便设置文字,图片等信息)
#import <UIKit/UIKit.h> @class StatusCellFrame; @interface StatusCell : UITableViewCell { UIImageView *_icon; // 头像 UILabel *_screenName; // 昵称 UILabel *_time; // 时间 UILabel *_source; // 来源 UILabel *_text; // 内容 UIImageView *_image; // 配图 UIImageView *_retweeted; // 被转发微博的父控件 UILabel *_retweetedScreenName; // 被转发微博作者的昵称 UILabel *_retweetedText; // 被转发微博的内容 UIImageView *_retweetedImage; // 被转发微博的配图 } // 每一个微博Cell都含有statusCellFrame这个模型对象的属性 @property (nonatomic, strong) StatusCellFrame *statusCellFrame; @end // MVC设计模式 : 一般都是设计一个模型Model 在视图View中拥有这个Model的实例
// // StatusCell.m // 新浪微博控 // // Created by WHB on 14-7-22. // Copyright (c) 2014年 whblap. All rights reserved. // #import "StatusCell.h" #import "StatusCellFrame.h" #import "Status.h" #import "UIImageView+WebCache.h" #import "User.h" @implementation StatusCell - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; if (self) { // 1.添加微博本身的子控件 [self addAllSubviews]; // 2.添加被转发微博的子控件 [self addReweetedAllSubviews]; } return self; } #pragma mark 添加微博本身的子控件 - (void)addAllSubviews { // 1.头像 _icon = [[UIImageView alloc] init]; [self.contentView addSubview:_icon]; // 2.昵称 _screenName = [[UILabel alloc] init]; _screenName.font = kScreenNameFont; [self.contentView addSubview:_screenName]; // 3.时间 _time = [[UILabel alloc] init]; _time.font = kTimeFont; [self.contentView addSubview:_time]; // 4.来源 _source = [[UILabel alloc] init]; _source.font = kSourceFont; [self.contentView addSubview:_source]; // 5.内容 _text = [[UILabel alloc] init]; _text.numberOfLines = 0; _text.font = kTextFont; [self.contentView addSubview:_text]; // 6.配图 _image = [[UIImageView alloc] init]; [self.contentView addSubview:_image]; } #pragma mark 被转发微博的子控件 - (void)addReweetedAllSubviews { // 1.被转发微博的父控件 _retweeted = [[UIImageView alloc] init]; [self.contentView addSubview:_retweeted]; // 2.被转发微博的昵称 _retweetedScreenName = [[UILabel alloc] init]; _retweetedScreenName.font = kRetweetedScreenNameFont; [_retweeted addSubview:_retweetedScreenName]; // 3.被转发微博的内容 _retweetedText = [[UILabel alloc] init]; _retweetedText.numberOfLines = 0; _retweetedText.font = kRetweetedTextFont; [_retweeted addSubview:_retweetedText]; // 4.被转发微博的配图 _retweetedImage = [[UIImageView alloc] init]; [_retweeted addSubview:_retweetedImage]; } - (void)setStatusCellFrame:(StatusCellFrame *)statusCellFrame { _statusCellFrame = statusCellFrame; Status *s = statusCellFrame.status; // 1.头像 _icon.frame = statusCellFrame.iconFrame; [_icon setImageWithURL:[NSURL URLWithString:s.user.profileImageUrl] placeholderImage:[UIImage imageNamed:@"Icon.png"] options:SDWebImageRetryFailed | SDWebImageLowPriority]; // 2.昵称 _screenName.frame = statusCellFrame.screenNameFrame; _screenName.text = s.user.screenName; // 3.时间 _time.frame = statusCellFrame.timeFrame; _time.text = s.createdAt; // 4.来源 _source.frame = statusCellFrame.sourceFrame; _source.text = s.source; // 5.内容 _text.frame = statusCellFrame.textFrame; _text.text = s.text; // 6.配图 if (s.picUrls.count) { _image.hidden = NO; _image.frame = statusCellFrame.imageFrame; // MyLog(@"pic---%@", s.picUrls); NSString *imageStr = s.picUrls[0][@"thumbnail_pic"]; NSURL *imageURL = [NSURL URLWithString:imageStr]; [_image setImageWithURL:imageURL placeholderImage:[UIImage imageNamed:@"Icon.png"] options:SDWebImageLowPriority | SDWebImageRetryFailed]; //#warning 配图的图片 } else { _image.hidden = YES; } // 7.被转发微博 if (s.retweetedStatus) { _retweeted.hidden = NO; _retweeted.frame = statusCellFrame.retweetedFrame; // 8.昵称 _retweetedScreenName.frame = statusCellFrame.retweetedScreenNameFrame; _retweetedScreenName.text = s.retweetedStatus.user.screenName; // 9.内容 _retweetedText.frame = statusCellFrame.retweetedTextFrame; _retweetedText.text = s.retweetedStatus.text; // 10.配图 if (s.retweetedStatus.picUrls.count) { _retweetedImage.hidden = NO; _retweetedImage.frame = statusCellFrame.retweetedImageFrame; [_retweetedImage setImageWithURL:[NSURL URLWithString:s.retweetedStatus.picUrls[0][@"thumbnail_pic"]] placeholderImage:[UIImage imageNamed:@"Icon.png"] options:SDWebImageRetryFailed | SDWebImageLowPriority]; } else { _retweetedImage.hidden = YES; } } else { _retweeted.hidden = YES; } } @end
2>.新建一个模型,作用是对cell里面的每一个控件设置frame 条件:
1>>.需要提供好一系列的CGRect类型的数据进行访问
2>>.提供一个接口来计算cell里面所有子控件的frame和cell的高度 如:- (void)setStatus:(Status *)status
// // StatusCellFrame.h // 微格 // // Created by WHB on 14-7-22. // Copyright (c) 2014年 whblap. All rights reserved. // #define kCellBorderWidth 10 #define kScreenNameFont [UIFont systemFontOfSize:17] #define kTimeFont [UIFont systemFontOfSize:13] #define kSourceFont kTimeFont #define kTextFont [UIFont systemFontOfSize:15] #define kRetweetedTextFont [UIFont systemFontOfSize:16] #define kRetweetedScreenNameFont [UIFont systemFontOfSize:16] #import <Foundation/Foundation.h> @class Status; @interface StatusCellFrame : NSObject // 一个StatusCellFrame对象 能 描述 一个StatusCell内部所有子控件的frame @property (nonatomic, strong) Status *status; // 根据status的内容来设置 各个属性的宽高 即提供的接口用来计算cell里面的所有控件的frame 和 cell @property (nonatomic, readonly) CGFloat cellHeight; // Cell的高度 @property (nonatomic, readonly) CGRect iconFrame; // 头像的frame @property (nonatomic, readonly) CGRect screenNameFrame; // 昵称 @property (nonatomic, readonly) CGRect timeFrame; // 时间 @property (nonatomic, readonly) CGRect sourceFrame; // 来源 @property (nonatomic, readonly) CGRect textFrame; // 内容 @property (nonatomic, readonly) CGRect imageFrame; // 配图 @property (nonatomic, readonly) CGRect retweetedFrame; // 被转发微博的父控件 @property (nonatomic, readonly) CGRect retweetedScreenNameFrame; // 被转发微博作者的昵称 @property (nonatomic, readonly) CGRect retweetedTextFrame; // 被转发微博的内容 @property (nonatomic, readonly) CGRect retweetedImageFrame; // 被转发微博的配图 @end
// // StatusCellFrame.m // 微格 // // Created by WHB on 14-7-22. // Copyright (c) 2014年 whblap. All rights reserved. // #import "StatusCellFrame.h" #import "Status.h" #import "User.h" @implementation StatusCellFrame - (void)setStatus:(Status *)status { _status = status; // 利用微博数据,计算所有子控件的frame // 整个cell的宽度 CGFloat cellWidth = [UIScreen mainScreen].bounds.size.width; // 1.头像 CGFloat iconX = kCellBorderWidth; CGFloat iconY = kCellBorderWidth; _iconFrame = CGRectMake(iconX, iconY, 50, 50); // 2.昵称 CGFloat screenNameX = CGRectGetMaxX(_iconFrame) + kCellBorderWidth; CGFloat screenNameY = iconY; CGSize screenNameSize = [status.user.screenName sizeWithFont:kScreenNameFont]; _screenNameFrame = (CGRect){{screenNameX, screenNameY}, screenNameSize}; // 3.时间 CGFloat timeX = screenNameX; CGFloat timeY = CGRectGetMaxY(_screenNameFrame) + kCellBorderWidth; CGSize timeSize = [status.createdAt sizeWithFont:kTimeFont]; _timeFrame = (CGRect){{timeX, timeY}, timeSize}; // 4.来源 CGFloat sourceX = CGRectGetMaxX(_timeFrame) + kCellBorderWidth; CGFloat sourceY = timeY; CGSize sourceSize = [status.source sizeWithFont:kSourceFont]; _sourceFrame = (CGRect) {{sourceX, sourceY}, sourceSize}; // 5.内容 CGFloat textX = iconX; CGFloat textY = CGRectGetMaxY(_sourceFrame) + kCellBorderWidth; CGSize textSize = [status.text sizeWithFont:kTextFont constrainedToSize:CGSizeMake(cellWidth - 2 * kCellBorderWidth, MAXFLOAT)]; _textFrame = (CGRect){{textX, textY}, textSize}; if (status.picUrls.count) { // 6.有配图 CGFloat imageX = textX; CGFloat imageY = CGRectGetMaxY(_textFrame) + kCellBorderWidth; _imageFrame = CGRectMake(imageX, imageY, 100, 100); } else if (status.retweetedStatus) { // 7.有转发的微博 // 被转发微博整体 CGFloat retweetX = textX; CGFloat retweetY = CGRectGetMaxY(_textFrame) + kCellBorderWidth; CGFloat retweetWidth = cellWidth - 2 * kCellBorderWidth; CGFloat retweetHeight = kCellBorderWidth; // 8.被转发微博的昵称 CGFloat retweetedScreenNameX = kCellBorderWidth; CGFloat retweetedScreenNameY = kCellBorderWidth; CGSize retweetedScreenNameSize = [status.retweetedStatus.user.screenName sizeWithFont:kRetweetedScreenNameFont]; _retweetedScreenNameFrame = (CGRect){{retweetedScreenNameX, retweetedScreenNameY}, retweetedScreenNameSize}; // 9.被转发微博的内容 CGFloat retweetedTextX = retweetedScreenNameX; CGFloat retweetedTextY = CGRectGetMaxY(_retweetedScreenNameFrame) + kCellBorderWidth; CGSize retweetedTextSize = [status.retweetedStatus.text sizeWithFont:kRetweetedTextFont constrainedToSize:CGSizeMake(retweetWidth - 2 * kCellBorderWidth, MAXFLOAT)]; _retweetedTextFrame = (CGRect){{retweetedTextX, retweetedTextY}, retweetedTextSize}; // 10.被转发微博的配图 if (status.retweetedStatus.picUrls.count) { CGFloat retweetedImageX = retweetedTextX; CGFloat retweetedImageY = CGRectGetMaxY(_retweetedTextFrame) + kCellBorderWidth; _retweetedImageFrame = CGRectMake(retweetedImageX, retweetedImageY, 100, 100); retweetHeight += CGRectGetMaxY(_retweetedImageFrame); } else { retweetHeight += CGRectGetMaxY(_retweetedTextFrame); } _retweetedFrame = CGRectMake(retweetX, retweetY, retweetWidth, retweetHeight); } // 11.整个cell的高度 _cellHeight = kCellBorderWidth; if (status.picUrls.count) { _cellHeight += CGRectGetMaxY(_imageFrame); } else if (status.retweetedStatus) { _cellHeight += CGRectGetMaxY(_retweetedFrame); } else { _cellHeight += CGRectGetMaxY(_textFrame); } } @end
3>.返回控制器,
在- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath方法中
1>>.创建一个自定义的Cell
2>>.实例化一个cellFrame
3>>.给Cell传递对应的cellframe;
在- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath方法中利用cellFrame
返回每一行cell的高度。
// // HomeViewController.m // 新浪微博控 // // Created by whblap on 14-6-25. // Copyright (c) 2014年 whblap. All rights reserved. // #import "HomeViewController.h" #import "UIBarButtonItem+WHBALP.h" #import "HttpTool.h" #import "Status.h" #import "User.h" #import "StatusManage.h" #import "StatusCell.h" #import "StatusCellFrame.h" @interface HomeViewController () { NSMutableArray *_statuses; // 所有的微博数据 } @end @implementation HomeViewController - (void)viewDidLoad { [super viewDidLoad]; [self buildNavigationBar]; [self loadStatusData]; } #pragma mark - build导航栏 - (void)buildNavigationBar { self.title = @"首页"; self.view.backgroundColor = [UIColor cyanColor]; // 添加给导航栏左图片按钮 self.navigationItem.leftBarButtonItem = [UIBarButtonItem barButtonItemWithImage:@"navigationbar_compose.png" highlightedImage:@"navigationbar_compose_highlighted.png" addTarget:self action:@selector(sendStatus)]; // 给导航栏添加右图片按钮 self.navigationItem.rightBarButtonItem = [UIBarButtonItem barButtonItemWithImage:@"navigationbar_pop.png" highlightedImage:@"navigationbar_pop_highlighted.png" addTarget:self action:@selector(popMenu)]; } #pragma mark - 加载微博数据 - (void)loadStatusData { _statuses = [NSMutableArray array]; // [HttpTool getWithPath:@"2/statuses/home_timeline.json" params:nil success:^(id JSON) { // NSArray *statuses = JSON[@"statuses"]; // JSON返回的数据默认是20条 为数组类型的对象 // // 将字典模型转化为模型对象(将模型对象添加到statuses微博数组中) // for (NSDictionary *dict in statuses) { // // // Status *status = [[Status alloc] initWithDict:dict]; // [_statuses addObject:status]; // } // NSLog(@"_____________%d",_statuses.count); // [self.tableView reloadData]; // } failure:^(NSError *error) { // NSLog(@"%@",error); // }]; // 微博管理 加载 [StatusManage getStatusesWithSuccess:^(NSArray *statues) { [_statuses addObjectsFromArray:statues]; [self.tableView reloadData]; } failure:^(NSError *error) { NSLog(@"%@",error); }]; } #pragma mark - 发送微博方法 - (void)sendStatus { MyLog(@"调用了发送微博方法"); } #pragma mark - 弹出菜单 - (void)popMenu { MyLog(@"调用了弹出菜单方法"); } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. NSLog(@"++++++++++++++++%d",_statuses.count); return _statuses.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; StatusCell *cell = [tableView dequeueReusableCellWithIdentifier:nil]; if (cell == nil) { // 创建一个自定义的cell cell = [[StatusCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier]; } // 实例化一个微博frame对象 StatusCellFrame *sCellFrame = [[StatusCellFrame alloc] init]; // 将访问服务器得到的微博数据赋值给微博frame对象的status模型 需要根据这个设置frame sCellFrame.status = _statuses[indexPath.row]; [cell setStatusCellFrame:sCellFrame]; return cell; } #pragma mark 返回每一行cell的高度 - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { StatusCellFrame *f = [[StatusCellFrame alloc] init]; f.status = _statuses[indexPath.row]; return f.cellHeight; } @end
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。