swift - UITableViewAutomaticDimension changes multiple times
问题描述
I have a project that uses iOS's default dynamic font. As so, I'm using UITableViewAutomaticDimension
for the height. I'm doing everything programmatically, so I set the constraints for my custom cells.
My Understanding of Constraints and UITableViewCell
s
From what I can understand about constraints, is that when you apply them to the superView
, the attributes that you set to be constrained will be forced to move based on the size of the superView
. But if you set the constraints to the contentView
of the UITableViewCell
, then the attribute that you set the constraints to will force the UITableViewCell
to change its height, width, ext.
CustomTableViewCell
import SnapKit
lazy var loadingIndicator: UIActivityIndicatorView = {
let loadingIndicator = UIActivityIndicatorView(activityIndicatorStyle: .gray)
loadingIndicator.sizeToFit()
loadingIndicator.autoresizingMask = [UIViewAutoresizing.flexibleHeight]
loadingIndicator.hidesWhenStopped = true
return loadingIndicator
}()
lazy var logoImageView: UIImageView = {
let logoImageView = UIImageView()
logoImageView.contentMode = UIViewContentMode.scaleAspectFit
logoImageView.backgroundColor = UIColor.white
logoImageView.clipsToBounds = true
return logoImageView
}()
lazy var storeLabel: UILabel = {
let storeLabel = UILabel()
storeLabel.sizeToFit()
storeLabel.font = UIFont.preferredFont(forTextStyle: .footnote)
storeLabel.adjustsFontForContentSizeCategory = true
storeLabel.textColor = UIColor.lightGray
return storeLabel
}()
lazy var priceLabel: UILabel = {
let priceLabel = UILabel()
priceLabel.sizeToFit()
priceLabel.font = UIFont.preferredFont(forTextStyle: .title1)
priceLabel.adjustsFontForContentSizeCategory = true
priceLabel.textColor = UIColor.black
return priceLabel
}()
lazy private var stackView: UIStackView = {
let stackView = UIStackView()
stackView.sizeToFit()
stackView.axis = UILayoutConstraintAxis.vertical
stackView.alignment = UIStackViewAlignment.leading
stackView.distribution = UIStackViewDistribution.fill
stackView.spacing = 0
return stackView
}()
lazy private var priceStackView: UIStackView = {
let priceStackView = UIStackView()
priceStackView.sizeToFit()
priceStackView.axis = UILayoutConstraintAxis.horizontal
priceStackView.alignment = UIStackViewAlignment.center
priceStackView.distribution = UIStackViewDistribution.fill
priceStackView.spacing = 0
return priceStackView
}()
override func draw(_ rect: CGRect) {
super.draw(rect)
let margins = contentView.layoutMarginsGuide
contentView.addSubview(logoImageView)
contentView.addSubview(stackView)
stackView.addArrangedSubview(storeLabel)
stackView.addArrangedSubview(priceStackView)
priceStackView.addArrangedSubview(loadingIndicator)
priceStackView.addArrangedSubview(priceLabel)
logoImageView.snp.makeConstraints { (make) in
make.left.equalTo(layoutMarginsGuide).offset(layoutMargins.left * 0.5)
make.centerY.height.equalTo(layoutMarginsGuide)
make.width.equalTo(logoImageView.snp.height)
}
stackView.snp.makeConstraints { (make) in
make.left.equalTo(logoImageView.snp.right).offset(layoutMargins.left * 1.5)
make.right.centerY.equalTo(margins)
make.height.equalTo(margins).offset(-15)
}
}
Output
Everything should work perfectly fine, but I don't get the desired height.
First height, a second later the height changes to this, and the final desired height is this. Am I setting the constraints wrong, or is this just a general iOS bug?
解决方案
The issue turned out to be the function that I was declaring the constraints inside of. Instead of using the draw(_ rect: CGRect)
override function, I needed to use the init(style: UITableViewCellStyle, reuseIdentifier: String?)
override function. The only reason I could think of for this is because the draw function happens after the init and after the margins have been set. So the constraints don't have time to update.
Here is the updated draw(_ rect: CGRect)
to init(style: UITableViewCellStyle, reuseIdentifier: String?)
function:
override func init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
let margins = contentView.layoutMarginsGuide
contentView.addSubview(logoImageView)
contentView.addSubview(stackView)
stackView.addArrangedSubview(storeLabel)
stackView.addArrangedSubview(priceStackView)
priceStackView.addArrangedSubview(loadingIndicator)
priceStackView.addArrangedSubview(priceLabel)
logoImageView.snp.makeConstraints { (make) in
make.left.equalTo(layoutMarginsGuide).offset(layoutMargins.left * 0.5)
make.centerY.height.equalTo(layoutMarginsGuide)
make.width.equalTo(logoImageView.snp.height)
}
stackView.snp.makeConstraints { (make) in
make.left.equalTo(logoImageView.snp.right).offset(layoutMargins.left * 1.5)
make.right.centerY.equalTo(margins)
make.height.equalTo(margins).offset(-15)
}
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
推荐阅读
- python - 使用递归函数创建 Python 脚本以显示前 n 个整数的总和,其中 n 由用户输入
- reactjs - 如何根据 URL 参数默认路由
- javascript - 向 generateRandomNumber 函数添加规则
- php - 在 WooCommerce 我的帐户页面上隐藏状态为(待付款)的订单
- javascript - TypeError:无法读取未定义的属性“get”:节点 js 错误
- swift - SwiftUI:如何使用 VStack、HStack 移动文本或其他内容?
- php - Saxon/C PHP apache 进程在调用 compileFromString 时卡在 FUTEX_WAIT_PRIVATE
- javascript - JS表输入值转JSON
- typo3 - 如何让 extbase 存储库尊重映射到 pages 表的模型的 l18n_cfg?
- ios - Swift Button 在整个区域都不可点击