超好用的 基于Masonry 的TableView 高度自适应扩展

一. 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 演示效果如下欢迎大家使用并吐槽......


Demo3.gif

Demo:

https://github.com/Unrealplace/LeeMasonryLayoutHeight

你可能感兴趣的:(超好用的 基于Masonry 的TableView 高度自适应扩展)