表视图单元格仅在屏幕外时自动布局
Posted
技术标签:
【中文标题】表视图单元格仅在屏幕外时自动布局【英文标题】:Table View Cells only AutoLayout when offscreen 【发布时间】:2014-10-05 01:31:25 【问题描述】:我正在使用 AutoLayout,并且由于某种原因,一旦 Table View 加载:
屏幕上的第一对表格视图单元格没有布局 正确 但是表格视图单元格在屏幕外滚动到时被布局 正确 但是当我向上滚动到未放置的原始表格视图单元格时 正确输出, 一旦他们离开屏幕然后又回到屏幕上所有突然 布局正确任何帮助将不胜感激,谢谢!
cellForRowAtIndexPath:
if ([model isKindOfClass:[FRSS self]])
FRSS *fDan = (FRSS *)model;
// configure cell
MRWebListTableViewCell *api1Cell = [tableView dequeueReusableCellWithIdentifier:@"YourAPI1Cell"];
// RSS
NSString *title = [NSString stringWithFormat:@"%@", fDan.title];
// Get string from XML
NSString *dateString = [self timeSincePublished:fDan.pubDate];
// Get description without tags
NSString *description = [self removehtmlTags:fDan.description];
NSString *link = [NSString stringWithFormat:@"%@", fDan.link];
api1Cell.labelHeadline.text = title;
api1Cell.labelDescription.text = description;
api1Cell.labelPublished.text = dateString;
// Top Image View
UIImageView *imv = [[UIImageView alloc]initWithFrame:CGRectMake(15, 20, 50, 50)];
imv.image=[UIImage imageNamed:@"e_r.png"];
[api1Cell.contentView addSubview:imv];
return api1Cell;
更新:即使在尝试了很多不同的事情之后,AutoLayout 仍然存在很多问题。
这与heightForRowAtIndexPath
有很大关系。最终需要通过将函数添加到 ViewController 代码中来手动设置它。为任何比正常估计单元格大得多的单元格手动设置它(即,如果其中有任何图像)。
【问题讨论】:
发现另一个问题并更新了我的答案 【参考方案1】:看来,self-sizing UITableView
单元格还是有一些缺陷的。
这是我们正在使用的解决方法。 虽然我不知道确切的底层机制,但这是我们发现的最简单的 hack。
@implemetation YourTableViewCell
- (void)setFrame:(CGRect)frame
if(frame.size.width != self.bounds.size.width)
[super setFrame:frame];
self.contentView.bounds = CGRectMake(0, 0, frame.size.width, frame.size.height);
[self.contentView layoutIfNeeded];
else
[super setFrame:frame];
// .. any other methods
@end
如果您无法编辑 UITableViewCell
子类,请在您的 UITableViewDataSource
中尝试此操作:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellIdentifier" forIndexPath:indexPath];
// setup cell ...
CGSize sysSize = [cell.contentView systemLayoutSizeFittingSize:CGSizeMake(tableView.bounds.size.width, CGFLOAT_MAX)];
cell.contentView.bounds = CGRectMake(0,0, sysSize.width, sysSize.height);
[cell.contentView layoutIfNeeded];
return cell;
顺便说一句,在您的代码中,这是一个问题。
// Top Image View
UIImageView *imv = [[UIImageView alloc]initWithFrame:CGRectMake(15, 20, 50, 50)];
imv.image=[UIImage imageNamed:@"e_r.png"];
[api1Cell.contentView addSubview:imv];
您不应在tableView:cellForRowAtIndexPath:
中创建/添加子视图View
。您的 NIB 中已经有 UIImageView
了,对吧?像这样使用它:
api1Cell.topImageView.image = [UIImage imageNamed:@"e_r.png"];
如果您的图像是动态的,最简单的解决方案是使用像 SDWebImage
这样的库
#import <SDWebImage/UIImageView+WebCache.h>
...
if ([model isKindOfClass:[FRSS self]])
FRSS *fDan = (FRSS *)model;
// configure cell
MRWebListTableViewCell *api1Cell = [tableView dequeueReusableCellWithIdentifier:@"YourAPI1Cell"];
...
// Top Image View
// for example: fDan.imageURL is a image URL string
[api1Cell.topImageView sd_setImageWithURL:[NSURLURLWithString: fDan.imageURL]
placeholderImage:[UIImage imageNamed: @"e_r.png"]];
【讨论】:
谢谢!我会尝试在我的代码中得到这个,也感谢关于图像视图的提示! 另外,我的图像视图不是静态图像,它是从 API 返回的任何图像。你的建议仍然适用吗?【参考方案2】:ios 8 的自动单元格高度似乎不太好用。我在 iOS 6 / 7 中遇到了类似的问题,在我更新到 iOS 8 后它仍然有效。所以也许你应该暂时去老学校。
这里有一些我的代码示例:AutoLayout multiline UILabel cutting off some text
在这里:AutoLayout uitableviewcell in landscape and on iPad calculating height based on portrait iPhone
长话短说,iOS 8 之前的方式涉及保留一个单元格的副本,仅用于计算 tableView:heightForRowAtIndexPath: 内的高度。但这对于处理多行 UILabel 是不够的。每次调用 layoutSubviews 时,我都必须继承 UILabel 以更新 preferredMaxLayoutWidth。
preferredMaxLayoutWidth “修复”似乎是我错过的神奇秘密。一旦我这样做了,我的大部分细胞都可以正常工作。
第二个问题我只需要我正确设置内容压缩阻力和内容拥抱属性,因此例如告诉标签拥抱文本将意味着它不会扩展以填充空白,这将导致单元格收缩。
完成这两件事后,我的单元格现在可以处理任何字体大小或任何数量的文本,而无需任何凌乱的布局代码。这需要学习很多东西,但我确实认为它最终得到了回报,因为我的应用中有很多动态内容。
编辑
在遇到我自己在 iOS 8 上的一些问题后,我添加了更多细节来解决这些非常奇怪的 autoLayout 错误。
使用我提到的代码,当单元格“行高”未设置为自定义时,它似乎不起作用。通过选择单元格并单击自动布局选项卡(所有内容压缩阻力设置等都在其中),可以在 IB 中找到此设置。按下复选框,它将填充一个临时高度。
其次,在我的代码中,我保留了一个单元格的本地副本,然后在 heightForRowAtIndexPath:
方法中多次重复使用它。每次调用时,这似乎都会使单元格高度增加很多。我不得不通过调用重新初始化本地副本:
localCopy = [self.tableView dequeueReusableCellWithIdentifier:@"mycell"];
似乎新的 Xcode 6 / iOS 8 更改非常不向后兼容 iOS 7,而且管理方式似乎完全不同。
希望这会有所帮助。
编辑 2
看完这个问题:iOS AutoLayout multi-line UILabel
我遇到了 iOS 7 / iOS 8 自动布局支持的另一个问题!!!我正在为 iOS 8 覆盖 layoutSubviews
我还需要覆盖 setBounds
以在调用 super 后更新 preferredMaxLayoutWidth
。 WTF 变苹果了!
似乎是IB中preferredMaxLayoutWidth
的设置有问题,因为iOS 7不能使用自动功能,如果你在多个设备上使用相同的UILabel
,它只会使用1宽度。因此,iOS 8 平板电脑上的UITableViewCell
会更大,因为在 iOS 8 iPhone 上,同一个单元格需要有 2 行。
【讨论】:
谢谢,我要试试这个! 我只是在寻找 iOS8 支持,这是否会减少您的一些答案?再次感谢西蒙! @Reez 我不确定仅针对 8 个目标是否会有所改善。我没有测试它,因为我不能为我当前的应用程序这样做。我不知道的是我第一次记录了一个针对苹果的错误,并且从那以后我发现了桶负载的问题。我昨天放弃了,将我的基础 SDK 设置为 7,它似乎解决了我所有的 autoLayout 问题。我在 8 中发现了另一个问题,对于一个有 7 个标签的单元格,它会出现其中 2 个被压扁,6 秒后它会在 3 上再次随机调用 setBounds 并更新单元格。我没有运行代码,也没有触摸单元格。它只是无缘无故地发生 @Reez 我已经在开发者论坛上发起了一个帖子,至少有一个评论说他们发现 8 太不稳定了。下周我将尝试看看我能否在 Xcode 6 中定位 7 并针对 iPhone 6 / 6+ 优化该应用程序。如果可以的话,我会放弃 8 个支持,直到苹果修复这些东西 很棒的西蒙,感谢您提供有关这方面的信息。如果 8 这么不稳定,那就有点疯狂了。【参考方案3】:我相信,如果您将子视图添加到 UITableViewCell
并使用 AutoLayout,由于自动调整大小,您会得到不想要的结果。尝试在 UITableViewCell 的子视图上调用 setTranslatesAutoresizingMaskINtoConstraints: NO
。
【讨论】:
这仅适用于 iOS8 吗?希望是,因为我肯定只需要支持iOS8。谢谢!!以上是关于表视图单元格仅在屏幕外时自动布局的主要内容,如果未能解决你的问题,请参考以下文章