博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
IOS 6.0+ Autolayout — UITableViewCell 高度调整
阅读量:6403 次
发布时间:2019-06-23

本文共 4729 字,大约阅读时间需要 15 分钟。

要实现的效果

要求:

一般titleLabel 仅显示一行标题,高度为固定。

imageview 大小也为固定。

detailLabel 宽度固定,但高度根据文本动态调整。 

cell 底部拒imageview 的底部以及detailLabel 底部高度都是大于等于20。

当detailLabel文字很少时,cell底部拒imageview底部维持20,这时detaillabel底部距cell 底部大于20. 

当detailLabel文字很多时,cell底部距imageview底部超过20,与detailLabel底部高度维持20.

 

storyboard上的准备工作 

注意将detailLabel numberOfLines 设为0

建好cell自定义AutoCell 类,关联好控件,事先准备好一些数据源

1
2
3
    
nameArray = [NSMutableArray arrayWithObjects:@
"蜗壳"
,@
"AI"
,@
"大詹皇"
,nil];
    
imageArray = [NSMutableArray arrayWithObjects:@
"u=4040080498,3072784853&fm=90&gp=0.jpg"
,@
"u=2384677404,2895132414&fm=21&gp=0.jpg"
,@
"u=262781505,2408318453&fm=21&gp=0.jpg"
, nil];
    
descriptionArray = [NSMutableArray arrayWithObjects:@
"蜗壳打球好潇洒,好飘逸,铁王之王"
,@
"AI,史上最矮状元,无冕之王,crossover简直厉害,观赏性强,永远的MVP!!!!"
,@
"最年轻的一万分先生,MVP,奥布莱恩杯,效率之王,天之骄子,全宇宙最强的球员没有之一,强突暴扣身体棒,发际线又高了,关键时刻又耸了,带领骑士夺冠吧,虽然看起来还没戏!!!!!!"
, nil];

实现tableview的委托方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//numberOfRows
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    
return 
3;
}
//cellForRow
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     
    
AutoTableViewCell *cell = (AutoTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@
"autoCell"
];
    
[cell.titleLabel setText:nil];
    
[cell.titleLabel setText:[nameArray objectAtIndex:indexPath.row]];
    
[cell.descriptionLabel setText:nil];
    
[cell.logoImageView setImage:[UIImage imageNamed:[imageArray objectAtIndex:indexPath.row]]];
    
[cell.descriptionLabel setText:[descriptionArray objectAtIndex:indexPath.row]];
    
return 
cell;
}

先不实现HeightForRow方法,直接运行,发现ios7,ios8上都没有得到想要的效果

IT'S SO BAD!!!

核心部分,HeightForRow方法实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    
static 
AutoTableViewCell *cell = nil;
    
static 
dispatch_once_t onceToken;
    
//只会走一次
    
dispatch_once(&onceToken, ^{
        
cell = (AutoTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@
"autoCell"
];
    
});
     
    
//calculate
    
CGFloat height = [cell calulateHeightWithtTitle:[nameArray objectAtIndex:indexPath.row] desrip:[descriptionArray objectAtIndex:indexPath.row]];
     
    
return 
height;
}

具体的计算高度方法是现在自定义cell类中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-(CGFloat)calulateHeightWithtTitle:(NSString*)title desrip:(NSString*)descrip
{
    
//这里非常重要
    
CGFloat preMaxWaith =[UIScreen mainScreen].bounds.size.width-108;
    
[self.detailLabel setPreferredMaxLayoutWidth:preMaxWaith];
    
[self.titleLabel setText:title];
    
//这也很重要
    
[self.detailLabel layoutIfNeeded];
    
[self.detailLabel setText:descrip];
    
[self.contentView layoutIfNeeded];
    
CGSize size = [self.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
    
//加1是关键
    
return 
size.height+1.0f;
}

几大需要注意的地方

  • 首先说为什么要设置 PreferredMaxLayoutWidth, 表示label的最大的布局宽度,label显示多少行与它的宽度肯定有关,所有这里要设置正确的宽度,但这里有点坑的地方

 

这是storyboard 上detailLabel 的该属性,默认是没有勾选的(automatic)表示系统自动计算最大布局宽度,但是查看官方文档,你会发现自动计算只有在ios8中才会有效果,低于ios8不会自动计算。这时你可能会说:那把它勾上吧!!!

如图,勾上之后你发现显示的是492,这是什么意思?这个数字是当前使用的storyboard 的宽度减去label到两边界的绝对距离。xcode6 为大尺寸storyboard 宽度600 ,减去 detailLabel 距左边界98,减去距右边界10,刚好492.

但是这样对吗?很明显不对,iphone 屏幕宽度不是已经有3种宽度了么?320、375(iphone6)、414(plus)

所以600很明显不对,应该用当前运行的宽度来减去108,所以这里勾不勾都是错,干脆不勾了直接代码算吧....

1
CGFloat preMaxWaith =[UIScreen mainScreen].bounds.size.width-108;
  • 关于layoutIfNeeded到底是干嘛的,我也是一知半解,只知道不加效果出不来,打算之后再去查阅...

  • 加1是关键 

1
2
[self.contentView systemLayoutSizeFittingSize:UILayoutFittingCompressedSize];
return 
size.height+1.0f;

这里size.height 实际上是我们要的contentview 的高度,但是我们如果直接将这个高度返回,就赋给了cell的高度,但是由于cell 分界线的原因,cell的高度比contentview高度多1,所以这里加1再返回。不要小看1像素,少了它效果还真就出不来!!!!

注意了这些,我们再运行,发现得到了想要的效果,切换模拟器,也没问题。

 

在ios6.0上测试

没有6.0的模拟器了,找了台6.0的真机,测试后效果如图

 

detailLabel的高度始终没有改变,维持在一行,但是可以发现cell的高度是对的,这似乎说明heightforrow方法没问题,那detailLabel为何没有自动拉伸呢?

再次检查了代码,原来问题出在cellforrow方法中,因为每个cell上的detailLabel的高度要拉伸就应该给每个 detailLabel设置最大布局宽度:preferredMaxLayoutWidth。之前做的仅仅只是在heightforrow里面的得到那个 用来计算的cell设置过。所以加了几句代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
     
    
AutoTableViewCell *cell = (AutoTableViewCell*)[tableView dequeueReusableCellWithIdentifier:@
"autoCell"
];
    
[cell.titleLabel setText:nil];
    
[cell.titleLabel setText:[nameArray objectAtIndex:indexPath.row]];
    
//补上的几句,给用来显示的DetailLabel 设置最大布局宽度
    
CGFloat preMaxWaith =[UIScreen mainScreen].bounds.size.width-108;
    
[cell.detailLabel setPreferredMaxLayoutWidth:preMaxWaith];
    
[cell.detailLabel layoutIfNeeded];
 
    
[cell.detailLabel setText:nil];
    
[cell.logoImageView setImage:[UIImage imageNamed:[imageArray objectAtIndex:indexPath.row]]];
    
[cell.detailLabel setText:[descriptionArray objectAtIndex:indexPath.row]];
    
return 
cell;
}

再次运行,可以看到在ios6中也得到了想要的效果,

IT'S perfect!!!

总之,研究了几天布局,发现ios好坑,各种陷阱,好在查阅了中外各种资料,最终还是实现了效果。

项目源码:

转载地址:http://xmjea.baihongyu.com/

你可能感兴趣的文章
html加载视频文件的方法
查看>>
Apache安装及虚机配置
查看>>
项目沟通管理和干系人管理
查看>>
构建LNMP平台
查看>>
Developer使用总结(1)
查看>>
我的友情链接
查看>>
oracle数据库之启动与关闭
查看>>
(19课)
查看>>
nginx结合keepalived做高可用负载集群服务
查看>>
《大企业云桌面运维实战》v1.13
查看>>
ANDROID 学习笔记 一
查看>>
IOS委托,实现两个UIView相互传值
查看>>
openSUSE日常使用
查看>>
HBase安装
查看>>
ASP.NET MVC 过滤器大全
查看>>
自学笔记:Activity的启动模式:FLAG_ACTIVITY_CLEAR_TOP和FLAG_ACTIVITY_REORDER_TO_FRONT
查看>>
网络层--IP协议(04)
查看>>
asp.net membership 修改密码
查看>>
JQuery高性能最佳实践
查看>>
Maven中Tomcat的日志格式调整
查看>>