简体   繁体   中英

UITableView corner radius doesn't work correctly

I've a tableview and I'd like to make the cells rounded. Every cell has a textfield inside. On "cellForRowAtIndexPath" I wrote:

cell.layer.cornerRadius = cell.frame.size.height/2;
cell.layer.masksToBounds = true;
cell.clipsToBounds = true;

but I can't understand why, but on one line cells sometimes the corner radius doesn't work causing to be like "pointed". Ps the content mode is set to be Aspect fit

Can someone help me?

I advise you to add a comtainer view to your cell controller, you will be able to manage the cell padding better with Auto Layout:

let containerView = UIView() 

set property of it:

containerView.backgroundColor = .red
containerView.clipsToBounds = true
containerView.translatesAutoresizingMaskIntoConstraints = false

Now add UIView and set constraints:

addSubview(containerView)
containerView.topAnchor.constraint(equalTo: topAnchor, constant: 0).isActive = true //change the constant to add padding (right and bottom are negative value)
containerView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: 0).isActive = true
containerView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0).isActive = true
containerView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: 0).isActive = true 

After that in cellForRowAt set yuor cell backgroundColor to clear

cell.backgoundColor = .clear
cell.containerView.layer.cornerRadius = cell.bounds.size.height/2;

This is the result with your corner radius applied to containerView:

在此处输入图片说明

Or set your tableView and cell like this:

class DummyViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

let tableView = UITableView()

override func viewDidLoad() {
    super.viewDidLoad()
    
    tableView.delegate = self
    tableView.dataSource = self
    tableView.translatesAutoresizingMaskIntoConstraints = false
    tableView.register(MyCell.self, forCellReuseIdentifier: "cellId")

    view.addSubview(tableView)
    tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    10
}

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    300
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! MyCell
    cell.layer.cornerRadius = cell.frame.size.height / 2;
    return cell
  }
}

Your cell:

class MyCell: UITableViewCell {

override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    
    backgroundColor = .blue
}

required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
 }
}

This is the result with your corner radius applied:

在此处输入图片说明

You are relying on the frame property of the cell, which is actually being managed by UIKit and the table view. In the place you refer to the frame, it might not actually be what you expect because it hasn't been displayed yet. (For example if your cells have dynamic heights and you are recycling an old cell with a different height then it will still have the old frame.)

You could try rounding inside the cell's implementation code itself. If you override the bounds property and use a didSet property observer you can set the corner radius there (use bounds instead of frame). This way even if the bounds changes 100 times you will always have the corner radius you expect.

As andym said, I'm relying on the frame property that haven't been defined yet. The best way to accomplish my goal is to put my code inside willDisplayCell method like this:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
    cell.layer.cornerRadius = cell.layer.bounds.size.height/2;
}

clipsToBounds 需要在 superview 上设置为 true,在您的情况下是 tableview。

You should configure the content view instead a cell it self

cell.contentView.layer.cornerRadius = 5 // or the value that you want
cell.contentView.layer.masksToBounds = true

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM