Masonry适配——(7)UITableView中自定义UITableViewCell高度自适应及计算

2023-05-16

https://github.com/potato512/SYDemo_Masonry

在UITableView列表的使用中,因为在自定义的UITableViewCell中页面相对复杂,所以会出现每一个cell都有不同的高度。这时候就需要根据实际内容进行cell的更新约束,其实说到底也就是哪些UI子视图应该显示,或隐藏,哪些UILabel标签高度是这个数值,哪些UILabel标签的高度是那个数值。

这样想的话,我们在研发时就可以根据实际的数据Model进行控制UI的显示,或隐藏,也就是更新UI的约束,以便设置UI的自适应显示;其次再计算出实际的高度用于在UITableView的代理回调方法中设置cell的高度。

先看下效果图



示例代码(model类、cell类)

1、自定义数据model

#import <Foundation/Foundation.h>

@interface TableViewModel : NSObject

@property (nonatomic, strong) NSString *title;
@property (nonatomic, strong) NSString *content;
@property (nonatomic, strong) NSString *imageName;

@property (nonatomic, assign) CGFloat height;

@end
#import "TableViewModel.h"
#import "TableViewCell.h"

@implementation TableViewModel

- (CGFloat)height
{
    if (!_height)
    {
        // 调用cell的方法计算出高度
        _height = [TableViewCell heightTableCellWithModel:self];
    }
    
    return _height;
    
}

@end

2、自定义UITableViewCell

#import <UIKit/UIKit.h>
#import "TableViewModel.h"

static NSString *const identifierTableViewCell = @"TableViewCell";
static CGFloat const heightTableViewCell = (10.0 + 30.0 + 10.0 + 30.0 + 10.0 + 80.0 + 10.0);

@interface TableViewCell : UITableViewCell

@property (nonatomic, strong) TableViewModel *model;

+ (CGFloat)heightTableCellWithModel:(TableViewModel *)model;

@end
#import "TableViewCell.h"

static CGFloat const originXY = 10.0;
static CGFloat const heightTitle = 30.0;
static CGFloat const sizeImage = 80.0;

@interface TableViewCell ()

@property (nonatomic, assign) BOOL didSetupConstraints;

@property (nonatomic, strong) UILabel *titleLabel;
@property (nonatomic, strong) UILabel *detailLabel;
@property (nonatomic, strong) UIImageView *iconImageView;

@end

@implementation TableViewCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self)
    {
        [self setUI];
    }
    
    return self;
}

#pragma mark - 视图

- (void)setUI
{
    [self.contentView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.width.mas_equalTo(WidthScreen);
    }];
    
    self.contentView.backgroundColor = [UIColor purpleColor];
    
    self.titleLabel = [[UILabel alloc] init];
    [self.contentView addSubview:self.titleLabel];
    [self.titleLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(originXY);
        make.left.mas_equalTo(originXY);
        make.right.mas_equalTo(-originXY);
        make.height.mas_equalTo(heightTitle);
    }];
    self.titleLabel.backgroundColor = [UIColor orangeColor];
    self.titleLabel.numberOfLines = 1;
    self.titleLabel.textAlignment = NSTextAlignmentLeft;
    self.titleLabel.textColor = [UIColor blackColor];
    
    UIView *currentView = self.titleLabel;
    
    self.detailLabel = [[UILabel alloc] init];
    [self.contentView addSubview:self.detailLabel];
    [self.detailLabel mas_makeConstraints:^(MASConstraintMaker *make) {
        make.top.mas_equalTo(currentView.mas_bottom).offset(originXY);
        make.left.mas_equalTo(originXY);
        make.right.mas_equalTo(-originXY);

        // 根据实际情况计算高度
    }];
    self.detailLabel.font = [UIFont systemFontOfSize:12.0];
    self.detailLabel.backgroundColor = [UIColor redColor];
    self.detailLabel.textColor = [UIColor yellowColor];
    self.detailLabel.textAlignment = NSTextAlignmentLeft;
    // 多行设置
    self.detailLabel.numberOfLines = 0;
    self.detailLabel.preferredMaxLayoutWidth = (WidthScreen - originXY * 2);
    [self.detailLabel setContentHuggingPriority:UILayoutPriorityRequired forAxis:UILayoutConstraintAxisVertical];
    
    currentView = self.detailLabel;
    
    // 图标
    self.iconImageView = [[UIImageView alloc] init];
    [self.contentView addSubview:self.iconImageView];
    [self.iconImageView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(originXY);
        
        // 根据实际情况计算top,高
    }];
    self.iconImageView.backgroundColor = [UIColor greenColor];
}

#pragma mark - setter

- (void)setModel:(TableViewModel *)model
{
    if (model)
    {
        NSString *title = model.title;
        self.titleLabel.text = title;
        
        NSString *content = model.content;
        self.detailLabel.text = content;

        NSString *name = model.imageName;
        if (name && 0 != name.length)
        {
            UIImage *image = [UIImage imageNamed:name];
            self.iconImageView.image = image;
        }
        
        // 特别注意:如果设置了计算得出的高度约束,可能会造成文本显示不全的情况
//        CGFloat heightText = [[self class] heightTextWithText:content];
//        [self.detailLabel mas_updateConstraints:^(MASConstraintMaker *make) {
//            make.height.mas_equalTo(heightText);
//        }];
        [self.iconImageView mas_updateConstraints:^(MASConstraintMaker *make) {
            make.top.mas_equalTo(self.detailLabel.mas_bottom).offset(originXY);
            make.size.mas_equalTo((name && 0 != name.length) ? CGSizeMake(sizeImage, sizeImage) : CGSizeZero);
        }];        
        [self layoutIfNeeded];
    }
}

+ (CGFloat)heightTableCellWithModel:(TableViewModel *)model
{
    // 初化高度
    CGFloat height = originXY + heightTitle;
    
    // 计算高度
    NSString *text = model.content;
    CGFloat heightText = [[self class] heightTextWithText:text];
    height += (originXY + heightText);
    
    // 图片
    NSString *image = model.imageName;
    if (image && 0 != image.length)
    {
        height += (originXY + sizeImage);
    }
    
    height += originXY;
    NSLog(@"heightTableCell = %f, heightText = %f", height, heightText);
    
    return height;
}

+ (CGFloat)heightTextWithText:(NSString *)text
{
    // 计算高度
    CGSize size = [text boundingRectWithSize:CGSizeMake((WidthScreen - 2 * originXY), MAXFLOAT) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:12.0]} context:nil].size;
    CGFloat heightText = size.height;
    
    return heightText;
}


@end

3、使用

#import "TableViewViewController.h"
#import "TableViewModel.h"
#import "TableViewCell.h"

@interface TableViewViewController () <UITableViewDataSource, UITableViewDelegate>

@property (nonatomic, strong) UITableView *mainTableView;
@property (nonatomic, strong) NSArray *array;

@end

@implementation TableViewViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    self.title = @"tableview";
    
    [self setUI];
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

#pragma mark - 视图

- (void)setUI
{
    [self.mainTableView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.size.equalTo(self.view);
    }];
}

#pragma mark - UITableViewDataSource, UITableViewDelegate

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.array.count;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    TableViewModel *model = self.array[indexPath.row];
    CGFloat height = model.height;
    
    NSLog(@"index = %ld, height:%@", indexPath.row, @(height));
    return height;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    TableViewCell *cell = (TableViewCell *)[tableView dequeueReusableCellWithIdentifier:identifierTableViewCell];
    if (cell == nil)
    {
        cell = [[TableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifierTableViewCell];
    }
    
    TableViewModel *model = self.array[indexPath.row];
    cell.model = model;    
    
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    
    TableViewModel *model = self.array[indexPath.row];
    NSLog(@"index = %ld, height = %@", indexPath.row, @(model.height));
}

#pragma mark - getter

- (UITableView *)mainTableView
{
    if (!_mainTableView)
    {
        _mainTableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStylePlain];
        [self.view addSubview:_mainTableView];

        _mainTableView.backgroundColor = [UIColor colorWithWhite:0.5 alpha:0.3];
        _mainTableView.delegate = self;
        _mainTableView.dataSource = self;
        
        // 设置为动态高度
        _mainTableView.estimatedRowHeight = UITableViewAutomaticDimension;
    }
    
    return _mainTableView;
}

- (NSArray *)array
{
    if (!_array)
    {
        NSArray *tmpArray = @[@"hello,我是iOS开发菜鸟。",@"很多iOS开发者应该都用过autolayout,如果用故事版和XIB的话非常好用,但是如果用纯代码的方式写的话就感觉这东西太啰嗦了,一点都不好用,还不如frame来得快,然而在公司项目中一般都是多人开发,因此还是以纯代码写的方式比较多。",@"一个国外大神推出了一套封装好autolayout框架Masnory,Masonry是一个轻量级的布局框架拥有自己的描述语法采用更优雅的链式语法封装自动布局简洁明了并具有高可读性而且同时支持iOS和Max OS X。",@"银行不改变,就让支付宝就改变银行,至少让银行睡不着。",@"其实押金池这个是有很多争议的,押金金融确实是令很多人高潮,也是摩拜被人议论得最多的一种盈利模式。押金池的本质是滚雪球,每个进来的用户都要交299块押金,那么这些押金是否可以用于下一批单车的采购,然后投放到其他城市,接着又有人用,又有押金,如此滚雪球似的增长。但是如果是这样的话,那么很多行业都有押金机制,那是否都可以这样玩呢?",@"其实在很多外行看来,几千万的注册量确实是很厉害,但是这个注册量的月活流量真的不怎么值得去关注,毕竟像摩拜这样的大公司,这些广告费只能是算做一个外快钱,并不能作为支持企业活下去。",@"政府自己就有公益车,有什么理由要补贴你,不竞争就不错了吧?政府关系参考滴滴至今,大谈这是优势的人,应该再考虑考虑。",@"类似广告,现阶段只是快钱,单车背后的人群,量级,产品回报率,这些东西究竟能在广告主品牌主值多少钱,打问号。",@"租金就是用户租用单车平台所得到的钱,一小时一块钱,那这样必须得有很高的使用频率才能够获取高的租金,但是摩拜其运营就是一个无底洞,单单这些租金恐怕是成本也很难赚回来。",@"融资仍然是摩拜如今最赚钱的手段,在1月4好,摩拜已经完成了D轮融资,融资金额为2.15亿美元,摩拜就是在不断的融资中拓展了其资金链,使其能够继续的生存下去。",@"有人分析出来摩拜利用GPS来分析用户的具体行为,通过统计用户的行为包装成数据卖给需要的大企业,但是这些数据具体参考价值也是用户的活跃地区在哪几个地方而已,具体价值还是有待研究的。",@"晚上跟公司领导和同事打麻将,散场后回到家,老婆问怎么样?我苦着脸说:“跟领导打牌能赢吗?输了五百多。”老婆听后点了点头,说:“下次别去打了,这次的钱就不从你下个月零用钱里扣了。”我爽快的答应了。第二天和老婆去菜场买菜,正巧遇到领导老婆,那老娘们一开口:“小律啊,你昨天手气真是太好了!一摞三,赢了一千多啊!”额,我特么差点没被这句话给噎死....。",@"表姐大龄剩女一枚,昨天有人给她介绍对象,表姐去了。见面地点约在一家餐厅,男人又矮又丑,表姐看不上。“本来我想走的,后来……”表姐没说完就害羞起来……我问:后来你被他的言谈吸引没走?表姐:他都走了,还点了一桌子菜,我怕浪费……",@"一天李靖对哪吒说,儿啊,你知道我为何总是对你不满吗?哪吒说难道是因为我太调皮了吗。李靖一巴掌就扇了上去,你个小逼崽子在你娘肚子里一待就是三年,急得为父手都能托塔了!哪吒母亲一笑说,怪不得塔下面有一个洞呢。",@"我四肢发达,好斗,一次在学校打伤一同学,去医院花了好多钱,不敢跟家里讲,于是找同学借,一同班女同学借给我最多……一段时间后,她没钱吃饭,催我还钱,我没办法,天天带她到朋友那里蹭饭……不久,她就变成我女朋友了…………终于,她将我带到她家见父母,居然遇到被我打伤的那个学生,他开口说:姐夫好!。",@"罗纳尔迪尼奥,个人荣誉:世界足球先生(2004,2005),金球奖(2005),南美足球先生(2013),金足奖(2009),国家队荣誉:美洲杯冠军(1999),世界杯冠军(2002),联合会杯冠军(2005),俱乐部荣誉:西甲冠军(2004,2005),欧洲冠军联赛冠军(2006),南美解放者杯冠军(2013),西班牙超级杯冠军(2004,2005)。",@"自从360免费后,一下子电脑的病毒似乎都消失了。",@"周鸿祎在一次节目上透露开始做360时,自己把别人卖到200元的软件,自己卖到25元,发现还是做不过别人。因为自己不是第一个做了,可能是第四个,第五个,市场都被别人占领了。",@"哪怕改变一个模式也是重新。",@"你现在做什么行业呢?是否能把自己卖的东西和360一样做到免费,而从其他地方赚钱?这是给每个创业者启发的。",@"一位锤子科技前员工在微博上发布长文《我为什么离开锤子科技》,向网友公开他离开锤子科技的原因。这位锤子科技前员工主要叙述了三个问题:一个是对上级的管理方式的不满,经常催促任务和越过中间级别布置详细任务;另一个是公司福利减少,没有中秋红包;最后一个是锤子科技的所谓弹性工作制度的问题,作者认为“所谓的弹性工作制就是一种可以让你每天加班到10点但是不用付薪水的制度。",@"马云曾经说过:“员工的离职原因很多,只有两点最真实: 1、钱,没给到位; 2、心,委屈了。”",@"华为的薪酬主要包括三部分:工资、奖金和分红;当然如若外派国外,还有外派补助+艰苦补助。华为的这种高薪政策及配“股票”的政策让员工极具“主人翁”意识:在公司大发展时,一起享受公司发展带来的红利;在公司困难时,能迎难而上与公司同舟共济。",@"华为不仅“舍得花钱”,更重要是“懂得分钱”,设计了一套“定岗定薪,易岗易薪”,意思就是工资薪酬是根据岗位来设定。",@"很多时候我们过高估计了机遇的力量,低估了规划的重要性,不明确的乐观主义者只知道未来越来越好,却不知道究竟多好,因此不去制定具体计划。他想在未来获利,但是却认为没有必要制定具体规划。"];
        
        NSMutableArray *modelArray = [[NSMutableArray alloc] init];
        for (int i = 0; i < tmpArray.count; i++)
        {
            TableViewModel *model = [[TableViewModel alloc] init];
            model.title = [NSString stringWithFormat:@"第 %@ 个cell", @(i)];
            model.content = tmpArray[i];
            model.imageName = (arc4random() % 10 % (i + 1) == 2 ? @"tianshi.png" : @"futou.png");
            if (i % 3 == 1)
            {
                model.imageName = nil;
            }
            
            [modelArray addObject:model];
        }
        
        _array = [[NSArray alloc] initWithArray:modelArray];
    }
    
    return _array;
}

@end


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Masonry适配——(7)UITableView中自定义UITableViewCell高度自适应及计算 的相关文章

  • 自定义绘制的 UITableViewCell 中的可访问性

    当您进行自定义绘图时 UITableViewCells 滚动速度会显着提高 但是辅助功能会中断 应该如何向这样的单元添加辅助功能支持 老问题了 但 iOS 已经内置了对这种辅助功能的支持 看看UIAccessibilityContainer
  • 一个 UITableView 中的两种不同的单元格类型

    大家好 我对如何在一个具有两个部分的 UITableView 中使用两种不同的单元格类型感到非常困惑 第一部分应返回一个大单元格 其中包含大量文本 另一部分应返回三个单元格 以导航到其他视图 我尝试过这样的 UITableViewCell
  • 在 UITableView 中创建隐藏的 UISegmentedControl

    与 iBooks 应用程序一样 当您下拉表格视图时 会出现搜索栏和分段控件 以允许您在两种类型的视图之间搜索和切换 当您向下拉得足够远时 它会停留在该位置 或者当您将桌面视图拉得足够远时 它会被隐藏 我正在尝试用一个来实现同样的事情UISe
  • 使用 Core Data Swift 对 TableView 和行进行分区

    我在 sqlite 中有两个表 代码由 XCode Generation 生成 class Event NSManagedObject NSManaged var startDate NSDate NSManaged var details
  • 当 tableView 的 allowedMultipleSelectionDuringEditing 属性为 YES 时,如何实现滑动删除功能?

    在 iOS 5 中 如果我设置allowsMultipleSelectionDuringEditing在 UITableView 上设置为 YES 然后滑动删除功能不再起作用 内置的邮件应用程序支持滑动删除和编辑模式下的多项选择 我也想这样
  • 检查 UITableViewCell 是否完全可见

    如何检查 UITableViewCell 在屏幕上是否完全可见 不被选项卡或导航栏切断 我可以使用以下代码获取可见单元格 NSArray indexes tableView indexPathsForVisibleRows 但我想排除屏幕中
  • 如何截断 UITableView Cell TextLabel 中的文本,使其不隐藏 DetailTextLabel?

    我有一份电话费率清单 textLabel是国家 地区并且detailTextLabel是我必须显示的速率 对于某些字符串 textLabel太长并且detailTextLabel变得隐藏 是否有一个设置可以自动调整文本 如果太长了 这是一个
  • 如何在 UI 视图上显示两个表

    我想在 UI 视图上使用和显示两个表 请让我知道如何执行此操作 任何相同的代码也将受到赞赏 谢谢 桑迪普 将 2 个 UITableView 添加到 IB 中的视图中 并将它们连接到文件所有者中的 2 个不同的出口 或者简单地分配不同的标签
  • 如何从 Xib 文件加载自定义 UITableViewCell?

    问题很简单 如何加载自定义UITableViewCell来自 Xib 文件 这样做可以让您使用 Interface Builder 来设计您的单元 由于内存管理问题 答案显然并不简单 这个线程 https stackoverflow com
  • 删除分组 UITableView 中的分隔符

    我需要使用自定义单元格创建分组表格视图 每个单元格必须有一个背景图像 以便一个单元格的图像会接触第二个单元格的图像 依此类推 我尝试将分隔符样式设置为 无 但我仍然得到单元格之间的透明分隔符 请帮我删除单元格之间的空间 祝你有美好的一天 谢
  • 在故事板中将 UITableView 的 rowHeight 设置为 UITableViewAutomaticDimension ?

    在 Xcode 6 中创建 iOS 8 应用程序时 如何设置 UITableViewrowHeight to UITableViewAutomaticDimension In WWDC 2014 第 226 场会议 表和集合视图中的新增功能
  • iOS UITableViewCell cell.imageView 设置圆角

    嘿我正在尝试设置cell imageView s cornerRadius 但似乎不起作用 cell imageView layer cornerRadius 9 它会起作用还是我应该添加自定义UIImageView在我的牢房里有圆角吗 我
  • 添加/删除带有动画的 UITableViewCell?

    我知道这听起来像是一个愚蠢的问题 但我到处都看过 我怎样才能做到这一点 我知道如何使用 swype to delete 方法来执行此操作 但是我如何在该函数之外执行此操作 请发布一些代码示例 Thanks Coulton self tabl
  • 具有自动布局的 UITableViewCell 中的 UILabel 高度错误

    我有一个UITableView单元格的固定高度为 100 点 这些单元格是在 xib 文件中创建的 该文件使用 3 个约束来固定UILabel到单元格的左 右和上边缘contentView 标签的垂直拥抱优先级设置为 1000 因为我希望单
  • 如何在 ios 7 上更改重新排序控制图像

    我正在寻找一种更改重新排序控件图像和大小的方法 我使用此代码来更改重新排序图像 void tableView UITableView tableView willDisplayCell UITableViewCell cell forRow
  • UISearchController 保留问题

    我正在尝试使用 UISearchController 但是我遇到了无法解决的保留问题 MainTableview 有两个部分 第1节 基于某些正则表达式过滤数据 第2节 All Data 我将 UISearchController 添加到我
  • 为什么我的 tableView 函数运行了 3 次?

    我有一个 UITableView 并且有执行它所需的方法之一 func tableView tableView UITableView numberOfRowsInSection section Int gt Int println sec
  • UITableView行高不变

    我创建了一个自定义单元格 我有一系列字典 对于我需要创建的字典值UILables 每个单元可能包含不同数量的UILabels 所以按照我的习惯UITableViewCell类我就是这样做的 void generateCell BOOL is
  • 自定义 UITableViewCell 错误

    我收到此错误 Terminating app due to uncaught exception NSUnknownKeyException reason
  • 在 UITableViewCell 内动态更改标签宽度

    我正在尝试建立一个自定义表格视图 正如您在图片中看到的 我在故事板一侧将标签的宽度默认设置为 160 磅 并在加载表格时动态更改宽度 我通过修改 cellForRowAtIndexPath 委托方法来实现此目的 因此 根据日期的长度 我设置

随机推荐