自定义非等高 Cell
1、自定义非等高 Cell介绍
1.1 代码自定义(frame)
- 新建一个继承自 UITableViewCell 的类。
- 重写 initWithStyle:reuseIdentifier: 方法。
- 添加所有需要显示的子控件(不需要设置子控件的数据和 frame, 子控件要添加到 contentView 中)。
- 进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片)。
- 提供 2 个模型。
- 数据模型: 存放文字数据\图片数据。
- frame 模型: 存放数据模型\所有子控件的 frame\cell 的高度。
- cell 拥有一个 frame 模型(不要直接拥有数据模型)。
- 重写 cell frame 模型属性的 setter 方法: 在这个方法中设置子控件的显示数据和 frame。
- frame 模型数据的初始化已经采取懒加载的方式(每一个 cell 对应的 frame 模型数据只加载一次)。
1.2 代码自定义(Autolayout)
- 新建一个继承自 UITableViewCell 的类。
- 重写 initWithStyle:reuseIdentifier: 方法。
- 添加所有需要显示的子控件(不需要设置子控件的数据和 frame, 子控件要添加到 contentView 中)。
- 进行子控件一次性的属性设置(有些属性只需要设置一次, 比如字体\固定的图片)。
- 设置 cell 上子控件的约束。
- 在模型中增加一个 cellHeight 属性,用来存放对应 cell 的高度。
- 在 cell 的模型属性 set 方法中调用 [self layoutIfNeed] 方法强制布局,然后计算出模型的 cellheight 属性值。
- 在控制器中实现 tableView:estimatedHeightForRowAtIndexPath: 方法,返回一个估计高度,比如 200。
- 在控制器中实现 tableView:heightForRowAtIndexPath: 方法,返回 cell 的真实高度(模型中的 cellHeight 属性)。
2、代码
2.1 XMGStatus.h
@interface XMGStatus : NSObject@property (strong, nonatomic) NSString *name;
@property (strong, nonatomic) NSString *text;
@property (strong, nonatomic) NSString *icon;
@property (strong, nonatomic) NSString *picture;
@property (assign, nonatomic, getter=isVip) BOOL vip;/** cell 的高度 */
@property (assign, nonatomic) CGFloat cellHeight;+ (instancetype)statusWithDict:(NSDictionary *)dict;@end
2.2 XMGStatus.m
@implementation XMGStatus+ (instancetype)statusWithDict:(NSDictionary *)dict {XMGStatus *status = [[self alloc] init];[status setValuesForKeysWithDictionary:dict];return status;
}@end
2.3 XMGStatusCell.h
@class XMGStatus;@interface XMGStatusCell : UITableViewCell+ (instancetype)cellWithTableView:(UITableView *)tableView;/** 模型数据 */
@property (nonatomic, strong) XMGStatus *status;@end
2.4 XMGStatusCell.m
#define MAS_SHORTHAND
#define MAS_SHORTHAND_GLOBALS#import "Masonry.h"@interface XMGStatusCell()@property (weak, nonatomic) UIImageView *iconView;
@property (weak, nonatomic) UILabel *nameLabel;
@property (weak, nonatomic) UIImageView *vipView;
@property (weak, nonatomic) UILabel *contentLabel;
@property (weak, nonatomic) UIImageView *pictureView;@end@implementation XMGStatusCell+ (instancetype)cellWithTableView:(UITableView *)tableView {static NSString *ID = @"status";XMGStatusCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];if (cell == nil) {cell = [[XMGStatusCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];}return cell;
}- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {if (self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]) {UIImageView *iconView = [[UIImageView alloc] init];[self.contentView addSubview:iconView];self.iconView = iconView;UILabel *nameLabel = [[UILabel alloc] init];[self.contentView addSubview:nameLabel];self.nameLabel = nameLabel;UIImageView *vipView = [[UIImageView alloc] init];[self.contentView addSubview:vipView];self.vipView = vipView;UILabel *contentLabel = [[UILabel alloc] init];contentLabel.numberOfLines = 0;// 设置 label 每一行文字的最大宽度contentLabel.preferredMaxLayoutWidth = [UIScreen mainScreen].bounds.size.width - 20;[self.contentView addSubview:contentLabel];self.contentLabel = contentLabel;UIImageView *pictureView = [[UIImageView alloc] init];[self.contentView addSubview:pictureView];self.pictureView = pictureView;}return self;
}- (void)layoutSubviews {[super layoutSubviews];CGFloat margin = 10;[self.iconView makeConstraints:^(MASConstraintMaker *make) {make.size.equalTo(30);make.left.top.offset(margin);}];[self.nameLabel makeConstraints:^(MASConstraintMaker *make) {make.top.equalTo(self.iconView);make.left.equalTo(self.iconView.right).offset(margin);}];[self.vipView makeConstraints:^(MASConstraintMaker *make) {make.size.equalTo(14);make.left.equalTo(self.nameLabel.right).offset(margin);make.centerY.equalTo(self.nameLabel.centerY);}];[self.contentLabel makeConstraints:^(MASConstraintMaker *make) {make.top.equalTo(self.iconView.bottom).offset(margin);make.left.offset(margin);// make.right.offset(-margin); // 可加可不加}];[self.pictureView makeConstraints:^(MASConstraintMaker *make) {make.size.equalTo(100);make.top.equalTo(self.contentLabel.bottom).offset(margin);make.left.offset(margin);}];
}- (void)setStatus:(XMGStatus *)status {_status = status;// 设置显示的数据self.iconView.image = [UIImage imageNamed:status.icon];self.nameLabel.text = status.name;if (status.isVip) {self.nameLabel.textColor = [UIColor orangeColor];self.vipView.hidden = NO;} else {self.nameLabel.textColor = [UIColor blackColor];self.vipView.hidden = YES;}self.contentLabel.text = status.text;if (status.picture) {self.pictureView.hidden = NO;self.pictureView.image = [UIImage imageNamed:status.picture];} else {self.pictureView.hidden = YES;}// 计算 cell 高度// 强制布局[self layoutIfNeeded];// 计算 cell 的高度if (self.pictureView.hidden) { // 没有配图_status.cellHeight = CGRectGetMaxY(self.contentLabel.frame) + 10;} else { // 有配图_status.cellHeight = CGRectGetMaxY(self.pictureView.frame) + 10;}
}@end
2.5 XMGStatusesViewController.m
@interface XMGStatusesViewController ()@property (strong, nonatomic) NSArray *statuses;@end@implementation XMGStatusesViewController- (NSArray *)statuses {if (_statuses == nil) {// 加载plist中的字典数组NSString *path = [[NSBundle mainBundle] pathForResource:@"statuses.plist" ofType:nil];NSArray *dictArray = [NSArray arrayWithContentsOfFile:path];// 字典数组 -> 模型数组NSMutableArray *statusArray = [NSMutableArray array];for (NSDictionary *dict in dictArray) {XMGStatus *status = [XMGStatus statusWithDict:dict];[statusArray addObject:status];}_statuses = statusArray;}return _statuses;
}#pragma mark - Table view data source- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {return self.statuses.count;
}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {XMGStatusCell *cell = [XMGStatusCell cellWithTableView:tableView];cell.status = self.statuses[indexPath.row];return cell;
}#pragma mark - 代理方法
// 返回每一行的高度
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {XMGStatus *staus = self.statuses[indexPath.row];return staus.cellHeight;
}/**
* 返回每一行的估计高度
* 只要返回了估计高度,那么就会先调用 tableView:cellForRowAtIndexPath: 方法创建 cell,
* 再调用 tableView:heightForRowAtIndexPath: 方法获取 cell 的真实高度
*/
- (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath {return 200;
}@end
2.6 运行效果图
- ---
3、其它设置方式
3.1 计算方式
- BookModel.h
@property(nonatomic, copy)NSString *title; @property(nonatomic, copy)NSString *detail; @property(nonatomic, copy)NSString *icon; @property(nonatomic, copy)NSString *price;
- BookCell.h
@property(nonatomic, retain)UILabel *titleLabel; @property(nonatomic, retain)UILabel *detailLabel; @property(nonatomic, retain)UIImageView *iconView; @property(nonatomic, retain)UILabel *priceLabel;
- 设置行高
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {// 从数据源数组中取出数据BookModel *bookModel = [myDataArray objectAtIndex:indexPath.row];// 计算 detailLabel 占用的高度CGFloat detialHeight = [bookModel.detail boundingRectWithSize:CGSizeMake(self.view.bounds.size.width - 40, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14]} context:nil].size.height;// 判断是否有图片if (bookModel.icon.length) {// 60 为图片的高度return 30 + detialHeight + 60 + 30;}else {return 30 + detialHeight + 30;} }
- 设置每一行显示的内容
// 设置每一行显示的内容 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {BookCell3 *cell = [tableView dequeueReusableCellWithIdentifier:@"test" forIndexPath:indexPath];BookModel *bookModel = [myDataArray objectAtIndex:indexPath.row];// 设置 titleLabelcell.titleLabel.text = bookModel.title;// 设置 detailLabel// 计算 detailLabel 的高度CGSize detialSize = [bookModel.detail boundingRectWithSize:CGSizeMake(self.view.bounds.size.width - 40, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: [UIFont systemFontOfSize:14]} context:nil].size;CGRect detialFrame = cell.detailLabel.frame;detialFrame.size.height = detialSize.height + 5; // 加偏移量 5,适应标点无法换行detialFrame.size.width = detialSize.width + 5;cell.detailLabel.frame = detialFrame; // 设置 detailLabel 的 framecell.detailLabel.text = bookModel.detail;// 判断是否有图片if (bookModel.icon.length) {// 设置 iconViewCGRect iconFrame = cell.iconView.frame;iconFrame.origin.y = detialFrame.origin.y + detialFrame.size.height;cell.iconView.frame = iconFrame;cell.iconView.image = [UIImage imageNamed: bookModel.icon];// 设置 priceLabelCGRect priceFrame = cell.priceLabel.frame;priceFrame.origin.y = iconFrame.origin.y + iconFrame.size.height;cell.priceLabel.frame = priceFrame;cell.priceLabel.text = bookModel.price;}else {// 设置 priceLabelCGRect priceFrame = cell.priceLabel.frame;priceFrame.origin.y = detialFrame.origin.y + detialFrame.size.height;cell.priceLabel.frame = priceFrame;cell.priceLabel.text = bookModel.price;}return cell; }
3.2 系统自动布局方式
- 自适应 cell 中较高的一个视图的高度。
- ImageView 与 Label 同行显示,且都设置了上下边缘约束,ImageView 的图片填充模式为 Aspect Fit,否则图片将会被拉长。
- 协议方法 方式设置
``` Objective-C
// 动态设置行高 (CGFloat)tableView:(UITableView )tableView estimatedHeightForRowAtIndexPath:(NSIndexPath )indexPath {
/
行高自适应 Label 高度
/secondTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"secondTableViewCell" forIndexPath:indexPath];
cell.secondLabel.text = [_labelArray objectAtIndex:indexPath.row];
return [cell.contentView systemLayoutSizeFittingSize:(UILayoutFittingCompressedSize)].height + 1;
}
// 属性变量 方式设置
self.tableView.estimatedRowHeight = 80;
self.tableView.rowHeight = UITableViewAutomaticDimension;
```
转载于:https://www.cnblogs.com/CH520/p/9420417.html
自定义非等高 Cell相关推荐
- 非等高cell实战(01)-- 实现微博页面
非等高cell实战(01)-- 实现微博页面 学习过UITableView.AutoLayout以及MVC的相关知识,接下来通过一个微博页面实战来整合一下. 首先看一下效果图: 需求分析 此页面为非等 ...
- 非等高cell实战--实现微博页面
代码地址如下: http://www.demodashi.com/demo/11639.html 前言 学习过UITableView.AutoLayout以及MVC的相关知识,接下来通过一个微博页面实 ...
- 【Android 应用开发】 自定义组件 宽高适配方法, 手势监听器操作组件, 回调接口维护策略, 绘制方法分析 -- 基于 WheelView 组件分析自定义组件
博客地址 : http://blog.csdn.net/shulianghan/article/details/41520569 代码下载 : -- GitHub : https://github.c ...
- R语言ggplot2可视化绘制线图(line plot)、使用gghighlight包突出高亮满足条件的线图、并保留其它线图的色彩(而不是灰色)自定义非高亮线图的透明度
R语言ggplot2可视化绘制线图(line plot).使用gghighlight包突出高亮满足条件的线图.并保留其它线图的色彩(而不是灰色)自定义非高亮线图的透明度 目录
- 纯代码计算不等高cell
不等高cell纯代码: 对应的GitHub 项目链接:https://github.com/liminting/CalculateCellDemo 不等高cell - 先设置高度rowH = 250 ...
- akka框架——异步非阻塞高并发处理框架
akka actor, akka cluster akka是一系列框架,包括akka-actor, akka-remote, akka-cluster, akka-stream等,分别具有高并发处理模 ...
- SpringBoot基于AOP实现自定义非空验证的注解
为了避免对大量参数进行过多的非空校验,我们可以自定义一个非空验证的注解,因为spring自带的@RequestParam并不能对参数进行非空 准备工作 首先需要创建一个spring boot项目,并引 ...
- android view设置按钮颜色_Android 酷炫自定义 View:高仿 QQ 窗帘菜单
作者:大公爵 链接:https://www.jianshu.com/p/cdb3d373fe37 介绍 不知道大家是否有印象,QQ 曾经有个版本用到了一种双向侧拉菜单,就像窗帘一样可以两边开合,并且伴 ...
- 让自定义view宽高成比例显示
有时候我们自定义一个View,比如ImageView,我们需要让它宽高按照一定的比例显示,例如在ImageView在GridView中显示,GridView设置了3列,由于ImageVIew的宽度会根 ...
最新文章
- (原创)按照一定的格式生成一定数量的随机数的例子
- No overload for 'OnStartup' matches delegate 'System.Windows.StartupEventHandler'
- Not so Mobile(二叉树递归输入同时建树){天平}
- NSIS脚本语言安装与编译
- FastCGI - Writing Hello World in FCGI with C++
- 有多个正整数存放在数组中,编写一个函数要求偶数在左边由小到大顺序放置,奇数在右边,也是由小到大顺序放置,Java实现...
- Dns信息收集工具集合
- VS2008引用webservice的奇怪BUG解决方案
- 发那科机器人注油_安川机器人加油保养流程
- 什么是QCIF? CIF?2CIF?4CIF?DCIF?
- ARM学习(8) axf 工具解析
- 配置多用户连接k8s
- 滴滴打车CTO张博:生死战役,技术和时间赛跑
- 定理在数学中的简写形式_数学公式定理中的特殊符号含义及读法
- 视觉伺服入门第二步:带你从经典论文阅读Visual Servo Control Part II: Advanced Approaches进阶版
- 快速寻找研究方向+发文章的方法!!按头安利!
- unity中3D数学相关类、属性、方法、用途总结+超级综合的案例
- 税务会计实务【13】
- Win10右键文件无响应崩溃
- POI导出Excel设置单元格背景色
热门文章
- 4 通讯_鼎信通讯:2019年净利润同比下降20.58% 拟10转4派1.04元
- 【文本分类】基于改进CHI和PCA的文本特征选择
- Navicat 2003-can't connect to MYSQL server on 'localhost'(10061)
- 大数据学习笔记二:Ubuntu/Debian 下安装大数据框架Hadoop
- php多个域名301重定向到主域名代码,Nginx 301和apache重定向域名规则方法(多个域名,单个域名)...
- php mysql sample,GitHub - BensonWuu/php-apache-mysql-sample
- java 简单 语言_将简单的表达式语言放入java中
- php程序耗时是负数,php 代码测试,代码越在前面越耗时
- canal下载 linux_canal实时同步mysql数据到redis或ElasticSearch
- 未找到要求的 from 关键字_莫纳什大学要求