所以我制作了自定义视图 ExpressionView 来可视化数学表达式。表达式的每一部分都是 UILabel,保存一个数字或运算,并且标签在 ExpressionView 内以右对齐的行对齐。我希望 ExpressionView 具有由外部自动布局约束定义的宽度,但高度应该是固有的,具体取决于我必须为给定宽度制作多少行标签。
对齐方法效果很好,我使用每个标签的frame.size和ExpressionView的宽度,进行数学计算,设置标签的框架位置,并计算包含所有行所需的高度。我还定义了这些,以便设置内在大小,并在每次 ExpressionLabel 宽度变化时重新布局标签:
override var intrinsicContentSize: CGSize {
let res = CGSize(width: UIView.noIntrinsicMetric,
height: CGFloat(self.contentHeight) //counted during self.layoutAllLabels()
)
return res
}
public override func layoutSubviews() {
super.layoutSubviews() //finish layout to get current label sizes and self width
let preHeight = self.contentHeight
self.layoutAllLabels() //layout all labels in current width, count required height
//if required height changed, relayout everything
if (preHeight != self.contentHeight) {
self.invalidateIntrinsicContentSize()
self.superview?.setNeedsLayout()
self.superview?.layoutIfNeeded()
}
}
当在普通 UIView 中通过自动布局约束设置 ExpressionLabel 时,一切都会正常工作。但是当 ExpressionLabel 固定在 UITableViewCell 的 contentView 内部时它会失败,并且我希望它定义单元格的高度。我的 UITableView 有自动调整单元格大小所需的这些行
self.estimatedRowHeight = 50
self.rowHeight = UITableView.automaticDimension
单个单元格的大小以某种方式发生并且通常是正确的,但通常也会给出无效的高度。它可能与单元重用(通过 dequeueReusableCells())有关,因为旧的高度可能保留在重用的单元中。但是,当它们应该在任何 ExpressionView.layoutSubviews() 调用中更新时,为什么它们没有更新呢?在 UITableView 中创建单元格时是否不会自动布局?如果没有,在哪里布局我的标签,以便它即使在 UITableView 中也能正确更新?当我知道最终单元格宽度,并可以根据它调整其子视图的固有高度时?
知道了!似乎自动尺寸化 UITableViewCell 的高度是通过调用从 UITableView 确定的systemLayoutSizeFitting()
的细胞。在我的单元类中,我重写了该方法,并在调用 super.systemLayoutSizeFitting() 之前调用 layoutIfNeeded() - 为了获得正确的尺寸。那行得通!也许我什至可以直接调用ExpressionView排列方法,而不是通过layoutIfNeeded(),但我会保持原样。
这是我的单元类中的覆盖:
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
//force layout of all subviews including ExpressionView, which
//updates ExpressionView's intrinsic height, and thus height of a cell
self.setNeedsLayout()
self.layoutIfNeeded()
//now intrinsic height is correct, so I can call super method
return super.systemLayoutSizeFitting(targetSize, withHorizontalFittingPriority: horizontalFittingPriority, verticalFittingPriority: verticalFittingPriority)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)