一、靜態cell和動態cell
一般比較固定的樣式可通過storyboard中的靜態cell或者動態cell進行操作,方便快捷高效。
靜態cell創建方式
動態cell創建方式
二、純代碼是實現自定義不等高cell
下面通過案例來實現用純代碼的方式來完成自定義不等高cell的實現。
項目需求:
以微博爲例,當別人髮狀態時,有的人發文字,有的人發文字和圖片,那麼如何實現這種方式呢?
項目思路:
在UITableViewCell中的系統樣式中不能滿足項目所需,那麼我們首先得想,通過自定義cell的方式來完成,至於高度不等,那麼我們可以在每一個cell中通過判斷哪個控件是最後一個,然後就取它的高度然後和cell底部間留有間距就完成了。
項目實現過程:
1.創建項目,導入圖片及plist文件
2.創建數據模型,用來進行plist字典數據轉模型
3.創建一個繼承自UITableViewCell的文件用來設置自定義cell以及數據的重寫
4.在控制器中遵守UITableViewDataSourse協議,創建代理對象,實現代理方法等。
項目代碼編碼過程:
1.創建項目,導入圖片及plist文件
2.創建ZJStatus數據模型
在ZJStatus.h中
/* 內容數據***********/
/* 頭像 /
@property (nonatomic ,copy)NSString *icon;
/* 暱稱 /
@property (nonatomic ,copy)NSString *name;
/* vip /
@property (nonatomic ,assign)BOOL vip;
/* 文字 /
@property (nonatomic ,copy)NSString *text;
/* 圖片 /
@property (nonatomic ,copy)NSString *picture;
在ZJStatus.m中不做任何操作
(3)創建ZJStatusCell文件用來設置自定cell以及重寫數據
在ZJStatusCell.h中
先導入@class ZJStatus;
將ZJStatus 所有屬性進行聲明
/* status的數據 /
@property (nonatomic,strong) ZJStatus *status;
在ZJStatusCell.m中
#import "ZJStatus.h"
#define KNameFont [UIFont systemFontOfSize:17]
#define KTextFont [UIFont systemFontOfSize:14]
@interface ZJStatusCell ()
// 聲明一些屬性
#import "ZJStatus.h"
#define KNameFont [UIFont
// 定義宏
systemFontOfSize:17]
#define KTextFont [UIFont systemFontOfSize:14]
@interface ZJStatusCell ()
/** 頭像 */
@property (nonatomic ,weak)UIImageView *iconImageView;
/** 暱稱 */
@property (nonatomic ,weak)UILabel *nameLabel;
/** vip */
@property (nonatomic ,weak)UIImageView * vipImageView;
/** 文字 */
@property (nonatomic ,weak)UILabel *TEXTLabel;
/** 圖片 */
@property (nonatomic ,weak)UIImageView *pictureImageView;
@end
@implementation ZJStatusCell
/**
* 添加子控件(把有可能顯示的子控件都加進去)
*/
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
// 1.暱稱
UIImageView *iconImageView = [[UIImageView alloc]init];
[self.contentView addSubview:iconImageView];
// 連線 建立關係
self.iconImageView = iconImageView;
// 2.標題
UILabel *nameLabel = [[UILabel alloc]init];
[self.contentView addSubview:nameLabel];
self.nameLabel = nameLabel;
// 設置文字大小
self.nameLabel.font = KNameFont;
// 連線 建立關係
self.nameLabel = nameLabel;
// 3.vip
UIImageView *vipImageView = [[UIImageView alloc]init];
vipImageView.image = [UIImage imageNamed:@"vip"];
// 圖片顯示格式
vipImageView.contentMode = UIViewContentModeCenter;
[self.contentView addSubview:vipImageView];
// 連線 建立關係
self.vipImageView = vipImageView;
// 4.文字
UILabel *TEXTlabel = [[UILabel alloc]init];
[self.contentView addSubview:TEXTlabel];
self.TEXTLabel = TEXTlabel;
// 設置文字大小
self.TEXTLabel.font = KTextFont;
// 連線 建立關係
self.TEXTLabel = TEXTlabel;
// 換行
self.TEXTLabel.numberOfLines = 0;
// 設置一個背景顏色
self.TEXTLabel.backgroundColor = [UIColor redColor];
// 5.配圖
UIImageView *pictureImageView = [[UIImageView alloc]init];
[self.contentView addSubview:pictureImageView];
self.pictureImageView = pictureImageView;
// 連線 建立關係
self.pictureImageView = pictureImageView;
}
return self;
}
// 佈局子控件
- (void)layoutSubviews{
#warning 一定要調用 [super layoutSubviews];
[super layoutSubviews];
CGFloat margin = 10;
// 1.設置頭像的位置
CGFloat iconX = margin;
CGFloat iconY = margin;
CGFloat iconW = 40;
CGFloat iconH = iconW;
self.iconImageView.frame = CGRectMake(iconX, iconY, iconW, iconH);
// 2.設置標題位置
CGFloat nameX = CGRectGetMaxX(self.iconImageView.frame) + margin;
CGFloat nameY = iconY;
// 計算文字所佔據的尺寸
NSDictionary *nameAttri = @{NSFontAttributeName :KNameFont
};
CGSize nameSize = [self.status.name sizeWithAttributes:nameAttri];
// 包裝成結構體
self.nameLabel.frame = (CGRect){{nameX,nameY},nameSize};
// 3.設置vip圖標
if (self.status.vip) {
CGFloat vipX = CGRectGetMaxX(self.nameLabel.frame) + margin;
CGFloat vipY = nameY;
CGFloat vipW = 14;
CGFloat vipH = nameSize.height;
self.vipImageView.frame = CGRectMake(vipX, vipY, vipW, vipH);
}
// 4.文字
CGFloat textX = iconX;
CGFloat textY = CGRectGetMaxY(self.iconImageView.frame) + margin;
CGFloat textW = self.contentView.frame.size.width - iconX * 2;
CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
NSDictionary *textSize = @{NSFontAttributeName:KTextFont
};
CGFloat textH = [self.status.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textSize context:nil].size.height;
self.TEXTLabel.frame = CGRectMake(textX, textY, textW, textH);
// 配圖
if (self.status.picture) {
CGFloat pictureX = textX;
CGFloat pictureY = CGRectGetMaxY(self.TEXTLabel.frame) +margin;
CGFloat pictureW = 100;
CGFloat pictureH = pictureW;
self.pictureImageView.frame = CGRectMake(pictureX, pictureY, pictureW, pictureH);
}
}
- (void)setStatus:(ZJStatus *)status{
_status = status;
self.iconImageView.image = [UIImage imageNamed:status.icon];
self.nameLabel.text = status.name;
self.TEXTLabel.text = status.text;
// 圖片
if (status.picture) {
self.pictureImageView.hidden = NO;
self.pictureImageView.image = [UIImage imageNamed:status.picture];
}
else {
self.pictureImageView.hidden = YES;
}
// vip 圖標
if (status.vip) {
self.vipImageView.hidden = NO;
self.nameLabel.textColor = [UIColor orangeColor];
}else{
self.vipImageView.hidden = YES;
self.nameLabel.textColor = [UIColor blackColor];
}
}
在控制器中:
#import "ZJStatus.h"
#import "ZJStatusCell.h"
// 導入第三方數據轉模型框架MJExtension
#import "MJExtension.h"
@interface ViewController ()
/** status的數組 */
@property (nonatomic,strong) NSArray *statuses;
@end
@implementation ViewController
- (NSArray *)statuses{
if (!_statuses) {
_statuses = [ZJStatus objectArrayWithFilename:@"statuses.plist"];
}
return _statuses;
}
NSString *ID = @"status";
- (void)viewDidLoad {
[super viewDidLoad];
// 註冊
[self.tableView registerClass:[ZJStatusCell class] forCellReuseIdentifier:ID];
}
#pragma mark - 數據源方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.statuses.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
ZJStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
cell.status = self.statuses[indexPath.row];
return cell
;
}
#pragma mark - 通過代理方法來算高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
// 從模型中取出數據
ZJStatus *status = self.statuses[indexPath.row];
CGFloat margin = 10;
CGFloat cellHeight = 0;
// 1.設置頭像的位置
CGFloat iconX = margin;
CGFloat iconY = margin;
CGFloat iconW = 40;
CGFloat iconH = iconW;
CGRect iconImageView = CGRectMake(iconX, iconY, iconW, iconH);
// 2.文字
CGFloat textX = iconX;
CGFloat textY = CGRectGetMaxY(iconImageView) + margin;
CGFloat textW = [UIScreen mainScreen].bounds.size.width - iconX * 2;
CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
NSDictionary *textSize = @{NSFontAttributeName:[UIFont systemFontOfSize:16.0]
};
CGFloat textH = [status.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textSize context:nil].size.height;
CGRect TEXTLabel = CGRectMake(textX, textY, textW, textH);
// 配圖
if (status.picture) {
CGFloat pictureX = textX;
CGFloat pictureY = CGRectGetMaxY(TEXTLabel) +margin;
CGFloat pictureW = 100;
CGFloat pictureH = pictureW;
CGRect pictureImageView = CGRectMake(pictureX, pictureY, pictureW, pictureH);
// 如果有圖片 cellHeight的Y就等於圖片的最大值
cellHeight = CGRectGetMaxY(pictureImageView);
}
else {
// 如果沒有圖片 cellHeight的Y就等於文字邊距的最大值
cellHeight = CGRectGetMaxY(TEXTLabel);
}
cellHeight += margin;
return cellHeight;
}
這種完成自定義不等高cell方式很low在實現代理方法來算高度的時候又把ZJStatusView中的設置位置方式寫了一遍,這樣寫性能會有所下降,爲了提高性能,可採用MVVM設計模式進行實現,後面會單另做MVVC設計模式的分享 。
三、根據文字來創建自適應大小方式。
// 自適應文字及高度顯示
CGFloat textX = iconX;
CGFloat textY = CGRectGetMaxY(iconImageView) + margin;
// 設置文字的自適應寬度 ,屏幕的寬度減去兩邊的間距
CGFloat textW = [UIScreen mainScreen].bounds.size.width - iconX * 2;
// 設置文字顯示的最大高度
CGSize textMaxSize = CGSizeMake(textW, MAXFLOAT);
// 字典包裝文字本身大小
NSDictionary *textSize = @{NSFontAttributeName:[UIFont systemFontOfSize:16.0]
};
// 算出文字的自適應高度
CGFloat textH = [status.text boundingRectWithSize:textMaxSize options:NSStringDrawingUsesLineFragmentOrigin attributes:textSize context:nil].size.height;
CGRect TEXTLabel = CGRectMake(textX, textY, textW, textH);
// 自適應文字寬度顯示
CGFloat nameX = CGRectGetMaxX(self.iconImageView.frame) + margin;
CGFloat nameY = iconY;
// 計算文字本身所佔據的尺寸
NSDictionary *nameAttri = @{NSFontAttributeName :[UIFont systemFontOfSize:14.0]
};
CGSize nameSize = [self.status.name sizeWithAttributes:nameAttri];
// 包裝成結構體
self.nameLabel.frame = (CGRect){{nameX,nameY},nameSize};