Reputation: 1404
Here is the UITableView
that I want to make:
In order to achieve this, I divided contentView
of cell into three parts.
1 - fromView: contains start time and class type. Height will be 30% of contentView
2 - infoView: contains clock image, class name and professor's name. Height will be 40% of contentView
.
3 - toView: contains end time and location. Height will be space that left(30%).
Firstly, before going to details, I decided to show this containers only. For understanding a problem, I painted them(green, red, blue respectively).
After adding them into the contentView
, here are the constraints I gave to those containers:
fromView.easy.layout(Top(), Left(), Right(), Height(*0.3).like(contentView))
infoView.easy.layout(Top().to(fromView), Left(), Right(), Height(*0.4).like(contentView))
toView.easy.layout(Top().to(infoView), Left(), Right(), Bottom())
Seems like everything is right. After launching, I thought that I will see them, but here is what happened:
I thought that cell does not know what size it needs to be, so I decided to implement following function:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 150
}
After this, UITableView
showed containers pretty correctly than before. But, I plan to add some UILabel
s and other views
into that containers(look at first picture). In other words, I don't know what size a cell needs to have. It needs to be kind of dynamic. Anyway, I tried to add those labels into the containers, maybe after that, a cell will figure out the the height. Here is how I did it:
func setupViews() {
fromView.addSubviews(fromTime, classType)
toView.addSubviews(toTime, room)
infoView.addSubviews(clockImage, teacherName, subjectName)
contentView.addSubviews(toView, fromView, infoView)
}
func setupConstraints() {
fromView.easy.layout(Top(), Left(), Right(), Height(*0.3).like(contentView))
infoView.easy.layout(Top().to(fromView), Left(), Right(), Height(*0.4).like(contentView))
toView.easy.layout(Top().to(infoView), Left(), Right(), Bottom())
fromTime.easy.layout(CenterY(), Left(8))
fromTime.setContentHuggingPriority(.required, for: .horizontal)
fromTime.setContentCompressionResistancePriority(.required, for: .horizontal)
classType.easy.layout(CenterY(), Left(8).to(fromTime))
clockImage.easy.layout(CenterY(), Left(16), Width(24), Height(24))
subjectName.easy.layout(CenterY(-8), Left().to(classType, .left), Right())
teacherName.easy.layout(Top(8).to(subjectName), Left().to(subjectName, .left), Right())
toTime.easy.layout(CenterY(), Left(8))
toTime.setContentHuggingPriority(.required, for: .horizontal)
toTime.setContentCompressionResistancePriority(.required, for: .horizontal)
room.easy.layout(CenterY(), Left(8).to(toTime))
}
But anyway, problem appeared again like this:
I think, the problem is that I give height to containers according to height of contentView
, but contentView
does not know its height. But I also don't know what height it needs to have, cause it needs to depend according to size of labels. So, how to solve this problem?
Upvotes: 0
Views: 751
Reputation: 19737
Look like what you want is a dynamic height calculated based on the content's AutoLayout. Update the delegates to return the UITableViewAutomaticDimension
for the heightForRowAt
and some good estimation, e.g., 150 for the estimatedHeightForRowAt
:
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 150
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
Then you can just set the content's size using autolayout, and the table will calculate the height of the cells for you dynamically.
Estimated height is used for scrolling purposes - a good estimate will provide you a good scrolling experience (dynamic height is calculated only when the cell is being displayed, thus for the yet undisplayed cells the tableView
will use estimation when scrolling).
Upvotes: 1
Reputation: 15218
Don't set heights for the containers. You have to make sure the top and bottom of the cell are connected through constraints. My recommendation is to just get rid of the containers, add all the labels and images to the cell directly, and create constraints like this.
Then set tableView.rowHeight = UITableView.automaticDimension
, or return UITableView.automaticDimension
from tableView(_:heightForRowAt:)
Upvotes: 2
Reputation: 101
Try by giving height constraint to your main view inside your cell.
Upvotes: 1