Reputation: 387
I have a customized UITableViewCell,and I want it to update height accroding my label text content.
But I try to use this code in my ViewController ViewDidLoad:
tableView.register(ChatRightTextTableViewCell.self, forCellReuseIdentifier: ChatRightTextTableViewCell.identifier)
tableView.estimatedRowHeight = 100.0
tableView.rowHeight = UITableViewAutomaticDimension
it doesn't seem to update the height.
What's wrong with me about my cell constraint?
Thanks.
import snapKit
import UIKit
class ChatRightTextTableViewCell: UITableViewCell {
static let identifier = "ChatRightTextTableViewCell"
var cellHeight: CGFloat = 0
var labelContent:UILabel = { ()->UILabel in
let ui:UILabel = GeneratorLabel()
ui.textColor = UIColor(red:0.20, green:0.20, blue:0.20, alpha:1.00)
ui.backgroundColor = UIColor.white
ui.font = defaultTextFont
ui.numberOfLines = 0
ui.lineBreakMode = NSLineBreakMode.byCharWrapping
ui.layer.cornerRadius = defaultButtonRadius
ui.layer.masksToBounds = true
return ui
}()
var labelDatetime:UILabel = { ()->UILabel in
let ui = GeneratorLabel()
ui.font = defaultMessageTimeFont
ui.textColor = defaultChatTimeColor
ui.numberOfLines = 0
return ui
}()
var icon:UIImageView = { ()->UIImageView in
let ui = GeneratorAvatarImageView()
ui.isUserInteractionEnabled = true
return ui
}()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
loadContent()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func layoutSubviews() {
super.layoutSubviews()
loadVFL()
}
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
func loadContent() {
backgroundColor = defaultBackgroundColor
selectionStyle = .none
contentView.addSubview(labelContent)
contentView.addSubview(labelDatetime)
contentView.addSubview(icon)
}
func loadVFL() {
let datetimeHeight:CGFloat = UIScreen.main.bounds.height*0.0195 //13
let contentWidth:CGFloat = contentView.bounds.width*0.62 //254.5
let iconLeftPadding:CGFloat = contentView.bounds.width*0.0266 //15
let contentAndDatePadding:CGFloat = UIScreen.main.bounds.height*0.0089 //6
let dateAndBottomPaddding:CGFloat = UIScreen.main.bounds.height*0.0090 //6
let topPadding:CGFloat = UIScreen.main.bounds.height*0.0149 //10
let nameLabelBottomPadding:CGFloat = UIScreen.main.bounds.height*0.0075 //5
let views = DictionaryOfInstanceVariables(self, objects: "labelContent","labelDatetime","icon")
let metrics = ["padding":iconLeftPadding,"contentAndDatePadding":contentAndDatePadding,"dateAndBottomPaddding":dateAndBottomPaddding,"nameLabelBottomPadding":nameLabelBottomPadding,"topPadding":topPadding]
labelContent.frame = CGRect(x: 0, y: 0, width: contentWidth, height: CGFloat.greatestFiniteMagnitude)
labelContent.sizeToFit()
icon.snp.makeConstraints { (make) -> Void in
make.width.equalTo(defaultChatroomIconWidth)
make.height.equalTo(defaultChatroomIconWidth)
make.centerY.equalToSuperview()
}
labelDatetime.snp.makeConstraints { (make) in
make.height.equalTo(datetimeHeight)
}
labelContent.backgroundColor = UIColor.red
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[labelContent]-padding-[icon]-padding-|", options: [], metrics: metrics, views: views))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[labelDatetime]-padding-[icon]-padding-|", options: [], metrics: metrics, views: views))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-topPadding-[labelContent]-contentAndDatePadding-[labelDatetime]-dateAndBottomPaddding-|", options: [], metrics: metrics, views: views))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-topPadding-[icon]", options: [], metrics: metrics, views: views))
}
}
Upvotes: 0
Views: 889
Reputation: 1521
Follows the below steps make your
UITableCell
height as dynamic according to the contents. That is very easy way to achieve all the steps.
UITableViewCell
.UITableViewCell
as given in diagram. left
, right
, top
and bottom
.inspector of attribute
from right side of your xCode.identity inspector
tab and add USER DEFINED RUNTIME ATTRIBUTES
key path -> layer.cornerRadius
, type -> Number
and value -> 5 / or what you want to give.Attribute Inspector
as choose as multipleLine
alignment.multipleLine
alignment and check Automatically Adjust Font
.Now Lets constraint on programming
//Set Both line in view did upload function with same format
self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 100.0
Remove Function if you have use
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
}
Upvotes: 0
Reputation: 1448
Autolayout would usually provide a warning in the case that you were using a xib. Here's your issue: Content Hugging Priority & Content Compression Resistance.
Content Hugging Priority is a value that indicates wether the content of a view should have priority to stretch it's superview over the superview's own constraints. In this case, your label doesn't have priority over the cell content view to stretch it, so it's getting squished.
Content Compression Resistance is, similarly, a value that indicates wether the content of a view has priority to limit it's superview's frame based on it's own. For example, if your cell wanted to go to height 1, but your label had a higher content compression resistance and a height of, let's say 2, the cell would be forced to limit itself to two.
A good explanation of this is provided here.
Let's solve your problem then.
Either assign a bigger content hugging priority, or content compression resistance. In your case it seems like the label doesn't have priority to stretch the cell, so set the hugging priority:
labelDatetime.setContentHuggingPriority(500, for: .vertical)
Alternatively, experiment with content compression to give the cell priority over controlling it's own height, while respecting the label's boundaries.
Upvotes: 0
Reputation: 20379
Gotcha,
If u had used a xib, you would have noticed the warning, because u have coded it and placed labels its difficult to guess the issue :)
You are using two labels which basically decides the height of the cell based on the content they show. But because both have Same Content Hugging priority on vertical axis, providing only top and bottom constraint to these labels will not suffice.
You have to set the content hugging priority over vertical axis to one of the label (which ever u think will have smaller content obviously) to higher value to provide enough data to calculate the dynamic height of the cell.
Summary :
Simply set
labelDatetime.setContentHuggingPriority(252, for: .vertical)
or
var labelDatetime:UILabel = { ()->UILabel in
let ui = GeneratorLabel()
ui.font = defaultMessageTimeFont
ui.textColor = defaultChatTimeColor
ui.numberOfLines = 0
ui..setContentHuggingPriority(252, for: .vertical)
return ui
}()
Upvotes: 1