我有一个UITableView
一个自定义UITableViewCell
在使用自动布局的故事板定义。 小区有几个多UILabels
。
该UITableView
似乎正确地计算单元格高度,但在最初的几个细胞高度不正确的标签之间的分歧。 滚动了一下后,一切正常(即最初甚至不正确的细胞)。
- (void)viewDidLoad {
[super viewDidLoad]
// ...
self.tableView.rowHeight = UITableViewAutomaticDimension;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TestCell"];
// ...
// Set label.text for variable length string.
return cell;
}
有什么,我可能会丢失,这是造成自动布局不能够完成其工作的第几次?
我创建了一个示例项目 ,其演示了此行为。
Answer 1:
我不知道这是明确记载或没有,但加入[cell layoutIfNeeded]
之前返回电池解决您的问题。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
TableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"TestCell"];
NSUInteger n1 = firstLabelWordCount[indexPath.row];
NSUInteger n2 = secondLabelWordCount[indexPath.row];
[cell setNumberOfWordsForFirstLabel:n1 secondLabel:n2];
[cell layoutIfNeeded]; // <- added
return cell;
}
Answer 2:
这为我工作,当其他类似的解决方案都没有:
override func didMoveToSuperview() {
super.didMoveToSuperview()
layoutIfNeeded()
}
这似乎是一个实际的错误,因为我非常熟悉的自动版式,以及如何使用UITableViewAutomaticDimension,但是我还是偶尔会遇到这个问题。 我很高兴我终于找到了,它作为一种变通方法。
Answer 3:
添加[cell layoutIfNeeded]
中cellForRowAtIndexPath
不会为最初滚出的视图细胞起作用。
也不与它作序[cell setNeedsLayout]
你还有滚动某些细胞并重新进入视野,以便正常调整。
这是非常令人沮丧,因为大多数开发者有动态类型,自动版式和自调整大小细胞正常工作 - 除了这恼人的情况。 这个bug影响我所有的“高”表视图控制器。
Answer 4:
我在项目中的一个有同样的经历。
为什么会发生?
细胞设计故事板与一些宽度对于一些设备。 例如400像素。 例如你的标签具有相同的宽度。 当它从故事板加载它具有宽度400像素。
这里有一个问题:
tableView:heightForRowAtIndexPath:
细胞布局之前调用它的子视图。
因此,计算标签和细胞宽度为400像素高度。 但是你用屏幕上的设备上运行,例如,320像素。 而这个自动计算高度不正确。 只是因为电池的layoutSubviews
后,才发生tableView:heightForRowAtIndexPath:
即使设置preferredMaxLayoutWidth
为您的标签在手动layoutSubviews
它不是帮助。
我的解决方案:
1)子类UITableView
并重写dequeueReusableCellWithIdentifier:forIndexPath:
设置单元格的宽度等于表的宽度和动力电池的布局。
- (UITableViewCell *)dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [super dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
CGRect cellFrame = cell.frame;
cellFrame.size.width = self.frame.size.width;
cell.frame = cellFrame;
[cell layoutIfNeeded];
return cell;
}
2)子类UITableViewCell
。 设置preferredMaxLayoutWidth
手动为您的标签layoutSubviews
。 你也需要手动布局contentView
,因为它没有细胞框架的变化后,自动布局(我不知道为什么,但它是)
- (void)layoutSubviews {
[super layoutSubviews];
[self.contentView layoutIfNeeded];
self.yourLongTextLabel.preferredMaxLayoutWidth = self.yourLongTextLabel.width;
}
Answer 5:
我有一个类似的问题,在第一负载,未计算行高,但一些滚动后或去到另一个画面,我回到这个屏幕行计算。 在第一次加载我的项目是从互联网上下载,并在第二负载我的项目是从核心数据首先被加载,并从互联网重新加载和我注意到,行高,在从互联网上重装计算。 所以,我注意到,当tableView.reloadData()赛格瑞动画过程中被调用(用推和赛格瑞存在同样的问题),未计算行高。 所以我隐藏在视图初始化的实现代码如下,并把活动装载机,以防止一个丑陋的效果给用户,我叫tableView.reloadData 300毫秒后,现在的问题就解决了。 我认为这是一个错误的UIKit但这种解决方法使的伎俩。
我把论文线(雨燕3.0)在我的项目加载完成处理
DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(300), execute: {
self.tableView.isHidden = false
self.loader.stopAnimating()
self.tableView.reloadData()
})
这解释了为什么有些人,把reloadData在layoutSubviews解决问题
Answer 6:
在我的情况下的UILabel的最后一行时被显示首次细胞被截断。 它发生相当随意地和大小的唯一方式是正确的滚动单元出来的观点,并把它带回来。 我尝试了所有显示到目前为止(layoutIfNeeded..reloadData)可能的解决方案,但没有为我工作。 诀窍是“自动收缩”设置为Minimuum字体比例 (0.5给我)。 试试看
Answer 7:
添加约束的表视图自定义单元格内的所有内容,然后估算表视图行的高度,并设置行HIGHT自动尺寸与一viewdid负荷:
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 70
tableView.rowHeight = UITableViewAutomaticDimension
}
为了解决这个问题初始加载问题适用layoutIfNeeded方法与自定义表格视图单元格:
class CustomTableViewCell: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
self.layoutIfNeeded()
// Initialization code
}
}
Answer 8:
我已经试过大部分回答这个问题,并不能得到任何人的工作。 我发现的唯一的功能性的解决办法是将以下内容添加到我UITableViewController
子类:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
UIView.performWithoutAnimation {
tableView.beginUpdates()
tableView.endUpdates()
}
}
该UIView.performWithoutAnimation
调用是必需的,否则你将看到正常的表视图动画作为视图控制器负载。
Answer 9:
设置preferredMaxLayoutWidth
帮助我的情况。 我加
cell.detailLabel.preferredMaxLayoutWidth = cell.frame.width
在我的代码。
另请参阅单行文本发生在的UILabel两条线和http://openradar.appspot.com/17799811 。
Answer 10:
我尝试了所有的解决方案在此页面中取消选中,但使用的大小类然后检查一遍解决我的问题。
编辑:取消勾选大小班引起了很多关于故事板的问题,所以我尝试另一种解决方案。 我在视图控制器填充的tableView ViewDidLoad
和ViewWillAppear
的方法。 这解决了我的问题。
Answer 11:
对我来说,这些方法都没有工作,但我发现标签有一个明确的Preferred Width
在Interface Builder中。 去除(取消选中“显性”),然后使用UITableViewAutomaticDimension
发挥预期。
Answer 12:
调用cell.layoutIfNeeded()
内cellForRowAt
工作对我来说iOS上的10和11的ios,但不能在iOS 9。
获得在iOS 9这项工作还可以,我叫cell.layoutSubviews()
和它的伎俩。
Answer 13:
我有一个调整标签问题,所以我的东东只是做
chatTextLabel.text = chatMessage.message chatTextLabel?.updateConstraints()建立后的文本
//完整的代码
func setContent() {
chatTextLabel.text = chatMessage.message
chatTextLabel?.updateConstraints()
let labelTextWidth = (chatTextLabel?.intrinsicContentSize().width) ?? 0
let labelTextHeight = chatTextLabel?.intrinsicContentSize().height
guard labelTextWidth < originWidth && labelTextHeight <= singleLineRowheight else {
trailingConstraint?.constant = trailingConstant
return
}
trailingConstraint?.constant = trailingConstant + (originWidth - labelTextWidth)
}
Answer 14:
以我为例,我是在更新周期等。 所以LabelText的设置后tableViewCell高度更新。 我删除异步块。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier:Identifier, for: indexPath)
// Check your cycle if update cycle is same or not
// DispatchQueue.main.async {
cell.label.text = nil
// }
}
Answer 15:
只要确保你没有设置在表视图“willdisplaycell”委托方法的标签文本。 设置“的cellForRowAtIndexPath”动态高度计算委托方法的标签文本。
别客气 :)
Answer 16:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{
// call the method dynamiclabelHeightForText
}
使用哪个动态返回高度该行的上述方法。 并分配相同的动态高度与该拉布勒您使用。
-(int)dynamiclabelHeightForText:(NSString *)text :(int)width :(UIFont *)font
{
CGSize maximumLabelSize = CGSizeMake(width,2500);
CGSize expectedLabelSize = [text sizeWithFont:font
constrainedToSize:maximumLabelSize
lineBreakMode:NSLineBreakByWordWrapping];
return expectedLabelSize.height;
}
此代码可以帮助你发现在标签显示文本的动态高度。
Answer 17:
在我的情况下,与细胞高度问题发生在初始表视图被加载后,与用户动作发生(攻丝上的按钮在具有改变细胞高度的效果的细胞)。 我一直无法得到的细胞改变其高度,除非我做的:
[self.tableView reloadData];
我曾尝试
[cell layoutIfNeeded];
但没有奏效。
Answer 18:
在斯威夫特3.我不得不打电话self.layoutIfNeeded()每一次我更新的可重复使用的单元格的文本。
import UIKit
import SnapKit
class CommentTableViewCell: UITableViewCell {
static let reuseIdentifier = "CommentTableViewCell"
var comment: Comment! {
didSet {
textLbl.attributedText = comment.attributedTextToDisplay()
self.layoutIfNeeded() //This is a fix to make propper automatic dimentions (height).
}
}
internal var textLbl = UILabel()
override func layoutSubviews() {
super.layoutSubviews()
if textLbl.superview == nil {
textLbl.numberOfLines = 0
textLbl.lineBreakMode = .byWordWrapping
self.contentView.addSubview(textLbl)
textLbl.snp.makeConstraints({ (make) in
make.left.equalTo(contentView.snp.left).inset(10)
make.right.equalTo(contentView.snp.right).inset(10)
make.top.equalTo(contentView.snp.top).inset(10)
make.bottom.equalTo(contentView.snp.bottom).inset(10)
})
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let comment = comments[indexPath.row]
let cell = tableView.dequeueReusableCell(withIdentifier: CommentTableViewCell.reuseIdentifier, for: indexPath) as! CommentTableViewCell
cell.selectionStyle = .none
cell.comment = comment
return cell
}
commentsTableView.rowHeight = UITableViewAutomaticDimension
commentsTableView.estimatedRowHeight = 140
Answer 19:
上述解决方案都没有工作,但下面的建议组合一样。
必须添加以下的viewDidLoad中()。
DispatchQueue.main.async {
self.tableView.reloadData()
self.tableView.setNeedsLayout()
self.tableView.layoutIfNeeded()
self.tableView.reloadData()
}
上述reloadData,setNeedsLayout和layoutIfNeeded的组合工作,但没有任何其他的。 可能是具体到项目的细胞虽然。 是的,不得不调用reloadData两次,使其工作。
还设置在viewDidLoad中以下
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = MyEstimatedHeight
在的tableView(_的tableView:UITableView的,cellForRowAt indexPath:IndexPath)
cell.setNeedsLayout()
cell.layoutIfNeeded()
Answer 20:
在我的情况下,在电池堆叠视图是造成问题。 这显然是一个错误。 一旦我删除了,问题解决了。
Answer 21:
我遇到了这个问题,并通过移动我的看法/标签初始化代码与固定它tableView(willDisplay cell:)
TO tableView(cellForRowAt:)
。
Answer 22:
问题是,最初的细胞加载,我们有一个有效的行高之前。 解决方法是强制执行表重装视图出现时。
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[self.tableView reloadData];
}
Answer 23:
以上解决方案的工作对我来说,什么工作是这个配方的魔力:给他们打电话顺序如下:
tableView.reloadData()
tableView.layoutIfNeeded() tableView.beginUpdates() tableView.endUpdates()
我的tableView数据从web服务填充,在我写上面的线路连接的回调。
文章来源: UITableView dynamic cell heights only correct after some scrolling