Search code examples
iosswiftiphoneuitableviewuibezierpath

UITableViewCell Rounded Corners Not Visible for Some Cells


My table uses rounded corner cells for the sections. However, on some iOS devices, the rounded corners on the right side are not visible. This may be less likely code-related and more on constraints end.

Screenshot below shows where rounded corners work (green box) and where they fail (red box) enter image description here

I tried the following code to add rounded corners which appears to work fine:

let path = UIBezierPath(roundedRect: cell.bounds,
           byRoundingCorners:[.topRight, .topLeft], // example
           cornerRadii: CGSize(width: 15, height:  15))
let maskLayer = CAShapeLayer()
maskLayer.path = path.cgPath
cell.layer.mask = maskLayer

My cell is initialized like this and I do not adjust its size when adding content:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: "mycell")

I have a feeling the content that is added to the cell pushes the cell width which hides the rounded corners. Any ideas what may be wrong?


Solution

  • You need to subclass the UITableViewCell and override the layoutSubview() function and set the path of the CAShapeLayer there.

    final class MyTableViewCell: UITableViewCell {
    
        private lazy var maskLayer = CAShapeLayer()
    
        var corners: UIRectCorner = [] {
            didSet {
                setNeedsLayout()
                updatePath(with: corners)
            }
        }
    
        override func layoutSubviews() {
            super.layoutSubviews()
            updatePath(with: corners)
        }
    
        private func updatePath(with corners: UIRectCorner) {
            let path = UIBezierPath(
                roundedRect: bounds,
                byRoundingCorners: corners,
                cornerRadii: CGSize(width: 15, height:  15)
            )
            maskLayer.path = path.cgPath
            layer.mask = maskLayer
        }
    
    }
    

    and then pass the corners in cellForRowAt

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = MyTableViewCell(
            style: UITableViewCell.CellStyle.default, reuseIdentifier: "mycell"
        )
        cell.corners = [.topRight, .topLeft]
    
        // ...
    
        return cell
    }