一. Masonry 使用简单复习传送门:
http://www.jianshu.com/p/99c418cd11f7 感谢作者
二. LeeMasonryLayoutHeight使用:
只需在tableview 的高度代理方法中调用下面这样代码,将会自动计算和缓存cell 的高度
优化了滑动速度:
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
LeeShowModel * model = _dataSource[indexPath.row];
NSString * cacheHeightKey = model.update == YES ?@"update":@"noupdate";
CGFloat height = [LeeShowCell lee_getHeightForTableView:tableView
cellConfig:^(UITableViewCell *sourceCell) {
[(LeeShowCell*)sourceCell configCellWith:model];
} cacheHeight:^NSDictionary *{
return @{
kLEECacheUniqueKey:[NSString stringWithFormat:@"%ld",(long)indexPath.row]//设置每一个高度字典的唯一标识。
,kLEECacheHeightKey:cacheHeightKey//设置不同状态的标识。比如某个cell 做了动画从新布局,高度要变化了。
,kLEERecalcutateForStateKey:@(NO)//标识别是否重新计算,一般设置为NO 防止好性能。
};
}];
return height;
}
在代码定义的Cell 中使用Masonry 进行布局,布局规则请参考上面的传送门:
cell 布局中要加入这句话 ,不然有时计算的高度有问题
contentLabel.numberOfLines = 0;
contentLabel.preferredMaxLayoutWidth = SCREEN_WIDTH - 20;
应该始终要加上上面一句
不然在6/6plus上就不准确了
原因:cell中的多行UILabel,如果其width不是固定的话(比如屏幕尺寸不同,width不同),
要手动设置其preferredMaxLayoutWidth。
因为计算UILabel的intrinsicContentSize需要预先确定其width才行
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {
[self setup];
}
return self;
}
-(void)setup{
contentImageView = [UIImageView new];
contentLabel = [UILabel new];
titleLabel = [UILabel new];
countBtn = [UIButton new];
[self.contentView addSubview:contentImageView];
[self.contentView addSubview:titleLabel];
[self.contentView addSubview:contentLabel];
[self.contentView addSubview:countBtn];
countBtn.backgroundColor = [UIColor redColor];
[countBtn setTitle:@"点我试试" forState:UIControlStateNormal];
[countBtn addTarget:self action:@selector(updateConstraintsCclik:) forControlEvents:UIControlEventTouchUpInside];
titleLabel.preferredMaxLayoutWidth = SCREEN_WIDTH - 20;
contentLabel.numberOfLines = 0;
contentLabel.preferredMaxLayoutWidth = SCREEN_WIDTH - 20;
[titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.contentView.mas_left).offset(10);
make.top.mas_equalTo(self.contentView.mas_top).offset(10);
}];
[contentLabel mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.contentView).offset(10);
make.right.mas_equalTo(self.contentView).offset(-10);
make.top.mas_equalTo(titleLabel.mas_bottom).offset(10);
}];
[contentImageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.mas_equalTo(contentLabel.mas_bottom).offset(15);
make.centerX.mas_equalTo(self.contentView.mas_centerX);
make.width.mas_equalTo(0);
make.height.mas_equalTo(0);
}];
[countBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.mas_equalTo(self.contentView.mas_left).offset(15);
make.right.mas_equalTo(self.contentView.mas_right).offset(-15);
make.top.mas_equalTo(contentImageView.mas_bottom).offset(10);
}];
self.lee_bottomOffSetToCell = arc4random() % 50; //设置cell 距离底部距离随机,以观察效果
self.isExpandedNow = YES;
}
本扩展的设计思路,和普通的没区别,就是在使用的时候计算出高度,缓存到本地,不需要每次都去好性能的计算,这样简单易用:
/**
外部接口获取cell的行高
@param tableView 外部传入的tableview
@param configBlock 配置cell 的数据源
@param cacheHeightBlock 缓存行高的block
@return 返回对应的行高
*/
+(CGFloat)lee_getHeightForTableView:(UITableView *)tableView
cellConfig:(LeeCellConfigBlock)configBlock
cacheHeight:(LeeCacheHeight)cacheHeightBlock{
NSAssert(tableView, @"tableview can't be nil");
//有缓存的行高,直接返回
if (cacheHeightBlock) {
@try {
NSDictionary * cacheKeys = cacheHeightBlock();
NSString * uniqueKey = cacheKeys[kLEECacheUniqueKey];//获取唯一标识的key
NSString * heightKey = cacheKeys[kLEECacheHeightKey];//获取高度的key
NSString * shouldUpdate = cacheKeys[kLEECacheForTableViewkey];//获取是否要更新的key
NSMutableDictionary * cacheDic = tableView.lee_CacheCellHeightDic[uniqueKey];//通过唯一标识获取缓存字典文件
NSString * cacheHeight = cacheDic[heightKey];//从缓存字典中读取高度
//如果缓存的高度为空 或者缓存大的高度字典个数为0 或者需要从新更新布局 : 就从新配置获取高度
if (tableView.lee_CacheCellHeightDic.count == 0
|| cacheHeight == nil
|| shouldUpdate.boolValue) {
//第一次计算获得高度:
CGFloat height = [self lee_heightForTableView:tableView cellConfig:configBlock];
if (cacheDic==nil) {//第一次每个唯一的cell 的高度缓存字典为空
cacheDic = [[NSMutableDictionary alloc] init];
tableView.lee_CacheCellHeightDic[uniqueKey] = cacheDic;//字典中没有这个健值对则创建
}
[cacheDic setObject:[NSString stringWithFormat:@"%f",height] forKey:heightKey];
return height;
}else if (tableView.lee_CacheCellHeightDic.count != 0
&& cacheHeight != nil
&& cacheHeight.integerValue != 0){
NSLog(@"缓存高度:%@",cacheHeight);
return cacheHeight.floatValue;
}
} @catch (NSException *exception) {
NSLog(@"%@",exception);
} @finally {
}
}
//没有缓存行高,从新计算
return [self lee_heightForTableView:tableView cellConfig:configBlock];
}
Demo 演示效果如下欢迎大家使用并吐槽......
Demo:
https://github.com/Unrealplace/LeeMasonryLayoutHeight