neo
neo

Reputation: 1404

Why UITableViewCell shrinks contentView?

Here is the UITableView that I want to make:

enter image description here

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:

enter image description here

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 UILabels 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:

enter image description here

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

Answers (3)

Milan Nosáľ
Milan Nosáľ

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

Rengers
Rengers

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.

enter image description here

Then set tableView.rowHeight = UITableView.automaticDimension, or return UITableView.automaticDimension from tableView(_:heightForRowAt:)

Upvotes: 2

Ranu Dhurandhar
Ranu Dhurandhar

Reputation: 101

Try by giving height constraint to your main view inside your cell.

Upvotes: 1

Related Questions