美文网首页互联网研究所
超好用的 基于Masonry 的TableView 高度自适应扩

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

作者: d20cdad48d2e | 来源:发表于2017-07-10 00:25 被阅读258次

    一. 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 高度自适应扩

        本文链接:https://www.haomeiwen.com/subject/ywiehxtx.html