How to correctly round edges of a table view cell with dynamic height

Viewed 532

I am having a problem with one of my table views. I am writing a messaging page for my app that uses a table view to display the messages sent and received. The table cells need to change height based on each cells content. I have the sizing working correctly but I now need to round the cells edges to fit the UI design. The way that I have done this in the past with non-dynamic heights is by calling a function to round each corner in the override function "layoutSubViews()" in the tableViewCell:

    func roundAllCorners(radius: CGFloat) {
        let allCorners: UIRectCorner = [.topLeft, .bottomLeft, .bottomRight, .topRight]
        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: allCorners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.layer.mask = mask
    }

If I try calling this function but the cell is dynamically sized then the left edge cuts off half a centimeter. If you scroll the cell off screen and back again though it fixes it. Hope you can find a solution to my problem, has been a pain in the neck for a while. Thanks.

3 Answers

It might be you also need to override the setter for frame and call it in there. Any any case this is not a good idea for multiple reasons. The thing is that table view cell has many views (including itself being a view) like content view and background view...

I suggest that you add yet another view on the content view which holds all your cell views. Then make this view a subclass and handle all the rounding in there. So from the storyboard perspective you would have something like:

- UITableViewCell
    - contentView
        - roundedContainer
            - imageView
            - button
            - label
            ...

The rounded view has (or should have) constraints so layoutSubViews should be enough to override for setting up corner radius.

You can have a neat class you can use to round your view like:

class RoundedView: UIView {

    @IBInspectable var cornerRadius: CGFloat = 0.0 {
        didSet {
            refresh()
        }
    }
    @IBInspectable var fullyRounded: Bool = false {
        didSet {
            refresh()
        }
    }


    override func layoutSubviews() {
        super.layoutSubviews()
        refresh()
    }

    private func refresh() {
        layer.cornerRadius = fullyRounded ? min(bounds.width, bounds.height) : cornerRadius
    }

}

As already mentioned by @iDeveloper it might be better to use cornerRadius of a layer. But if you need to use a shape layer you can do that as well in this class.

Make sure to clip bounds on this view.

Make sure you RELOAD THE TABLEVIEW after calling your function

yourTableView.reloadData() 

You can use self sizing table view cell according to the content. Now you can follow the previous implementation for rounded corner cell.

Place the below code inside viewDidLoad.

tableView.estimatedRowHeight = YourEstimatedTableViewHeight tableView.rowHeight = UITableViewAutomaticDimension

Note: You have to give the top and bottom constraints to the content properly.

For detailed implementation you can follow self-sizing-table-view-cells

Related