在单元格内设置视角半径的问题?

时间:2017-05-10 08:50:05

标签: ios uitableview tableviewcell cornerradius

我有一个自定义UITableView单元格。我正在设置它的左下角&右下角半径。我在cellForAtindexPath设置角半径。下面是

的代码
  if indexPath.row == 9 {

    recipeInfoCell.outerView.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 10)
    recipeInfoCell.layoutSubviews()
    recipeInfoCell.layoutIfNeeded()
  }
  else  {

    recipeInfoCell.outerView.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 0)
    recipeInfoCell.layoutSubviews()


  }

现在,当我第一次启动tableview时,它没有设置任何角半径。但是当我再次滚动时,它正在设置角半径。

我创建了UIView的扩展名,其中有一个设置角半径的函数

  func roundCorners(corners:UIRectCorner, radius: CGFloat) {

    let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
    let mask = CAShapeLayer()
    mask.path = path.cgPath
    self.layer.mask = mask
  }

请告诉我如何解决这个问题?

8 个答案:

答案 0 :(得分:13)

我不认为在cellForRow atIndexPath中设置角半径是个好主意。原因是,在UITableView的生命周期中多次调用此函数,您只需要设置一次角半径,并且在初始化单元时也是如此。基于indexPath更改角半径也会影响UITableView的性能。

更好的方法是创建两个单元格,一个角半径为0,另一个为10,并使用基于indexPath的单元格。

然后,您可以将cornerRadius设置逻辑放在自定义单元格中的layoutSubview函数中。

如果你只想在tableView方法中这样做,正确的方法是在willDisplayCell中进行,因为在调用之后,单元格的layoutSubviews函数被调用。

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        if indexPath.row % 2 == 0 {
            let path = UIBezierPath(roundedRect: cell.contentView.bounds, byRoundingCorners: [.bottomRight, .bottomLeft], cornerRadii: CGSize(width: 10, height: 10))
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            cell.contentView.layer.mask = mask
        } else {
            let path = UIBezierPath(roundedRect: cell.bounds, byRoundingCorners: [.bottomRight, .bottomLeft], cornerRadii: CGSize(width: 0, height: 0))
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            cell.contentView.layer.mask = mask
        }
    }

更新时间:2017年5月19日

当您要舍入并放置阴影的视图与单元格的内容视图的大小相同时,上述概念将正常工作。但如果它与此有什么不同,它就行不通。

上述声明的原因是,在调用willDisplayCell时,上面的代码使用cell.contentView.bounds,其他视图尚未计算。因此,当我们将使用另一个视图时,我们将不得不使用该视图的界限来计算掩码的帧,我们将与实际帧不同。

在阅读了这一点之后,我发现,做这种事情是通过覆盖UITableViewCell的draw(_ rect: CGRect)功能。因为此时,视图的大小已经正确计算,我们可以创建一个正确的框架。

以下是自定义UITableViewCell类的代码:

override func draw(_ rect: CGRect) {
        let path = UIBezierPath(roundedRect: self.outerView.bounds, byRoundingCorners: [.bottomRight, .bottomLeft], cornerRadii: CGSize(width: 10, height: 10))
        let mask = CAShapeLayer()
        mask.path = path.cgPath
        self.outerView.layer.mask = mask

        let shadowLayer = CAShapeLayer()
        shadowLayer.shadowPath = path.cgPath
        shadowLayer.frame = self.outerView.layer.frame
        print(shadowLayer.frame)
        shadowLayer.shadowOffset = CGSize(width: 0, height: 0)
        shadowLayer.shadowColor = UIColor.black.cgColor
        shadowLayer.shadowOpacity = 0.9
        self.contentView.layer.insertSublayer(shadowLayer, below: self.outerView.layer)
        super.draw(rect)
    }

答案 1 :(得分:7)

将圆角代码放在主队列中,如下所示:

if indexPath.row == 9 { dispatch_async(dispatch_get_main_queue(),{
recipeInfoCell.outerView.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 10)
   })} else{
 dispatch_async(dispatch_get_main_queue(),{
recipeInfoCell.outerView.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 0)
}) }

答案 2 :(得分:5)

尝试在Custom UITableViewCell的layoutSubviews()中编写这些代码行

override func layoutSubviews() {
super.layoutSubviews()
self.outerView.roundCorners(corners: [.bottomLeft, .bottomRight], radius: 10)
}

答案 3 :(得分:3)

为了在swift中获取它,我只使用创建一个UIButton的子类,如下所示

(在项目的任何.swift文件中)

//MARK: Custom Class for UIView
open class CustomView: UIView {
    open func drawViewsForRect(_ rect: CGRect) {
        fatalError("\(#function) must be overridden")
    }

    open func updateViewsForBoundsChange(_ bounds: CGRect) {
        fatalError("\(#function) must be overridden")
    }

}

然后在相同或不同的.swift文件中定义以下方法,如下所示

    //MARK: - UIView Property Class
@IBDesignable open class CView : CustomView{

    @IBInspectable dynamic open var borderColor: UIColor = UIColor.clear{
        didSet{
            updateBorderColor()
        }
    }

    @IBInspectable dynamic open var borderWidth: CGFloat = 1.0{
        didSet{
            updateBorderWidth()
        }
    }

    @IBInspectable dynamic open var cornerRadius: CGFloat = 0.0{
        didSet{
            updateBorderRadius()
        }
    }

    @IBInspectable dynamic open var shadowColor: UIColor?{
        didSet{
            updateShadowColor()
        }
    }

    @IBInspectable dynamic open var shadowRadius: CGFloat = 0.0{
        didSet{
            updateShadowRadius()
        }
    }

    @IBInspectable dynamic open var shadowOpacity: Float = 0.0{
        didSet{
            updateShadowOpacity()
        }
    }

    @IBInspectable dynamic open var shadowOffSet: CGSize = CGSize(width: 0.0, height: 0.0){
        didSet{
            updateShadowOffset()
        }
    }

    //Update Borders Properties
    open func updateBorderColor(){
        self.layer.borderColor = borderColor.cgColor
    }
    open func updateBorderRadius(){
        self.layer.cornerRadius = cornerRadius
    }
    open func updateBorderWidth(){
        self.layer.borderWidth = borderWidth
    }

    //Update Shadow Properties
    open func updateShadowColor(){
        self.layer.shadowColor = shadowColor?.cgColor
        self.clipsToBounds = false;
        self.layer.masksToBounds = false;
    }
    open func updateShadowOpacity(){
        self.layer.shadowOpacity = shadowOpacity
        self.clipsToBounds = false;
        self.layer.masksToBounds = false;
    }
    open func updateShadowRadius(){
        self.layer.shadowRadius = shadowRadius
        self.clipsToBounds = false;
        self.layer.masksToBounds = false;
    }
    open func updateShadowOffset(){
        self.layer.shadowOffset = CGSize(width: shadowOffSet.width, height: shadowOffSet.height)
        self.layer.shadowColor = shadowColor?.cgColor
        self.clipsToBounds = false;
        self.layer.masksToBounds = false;
    }
}

然后,只需在设计时为任何视图控制器在storyboard中分配CView类,并为该视图的属性检查器中的属性提供所需的值

在故事板中

1)视图类如此

set calls of view

2)像这样设置属性

Property like this

3)这将在此设计的侧面显示视图

view in storyboard

通过这种方式,您甚至可以直接在设计构建器中看到阴影或角半径,即在故事板视图的侧面,如第三张图像。

答案 4 :(得分:2)

如果我理解正确的话,你想要一个特定的细胞到圆角。这是我的解决方案。虽然我有点迟,但我试着帮助别人。 :)我刚刚将我的解决方案添加为图片。

第1步:

创建了一个自定义Cell并执行了一些必要的步骤。

enter image description here enter image description here

下面是左下角和右下角的代码。对于编码风格较差的原因:

enter image description here

下面是我的视图控制器配置,用于显示带圆角单元格的tableView。

enter image description here

enter image description here

以下是真实的时刻:

enter image description here

答案 5 :(得分:0)

我从(https://stackoverflow.com/a/44067058/2781088)参考并修改了代码,现在它对我有用:

将以下代码添加到自定义单元格类中:

enum cellStyle: Int {
    case Normal = 0, Rounded
}

class CustomTableCell:UITableViewCell {
    var cellType: Int = 0 {
        didSet {
            let maskLayer = CAShapeLayer()
            let cell: cellStyle = cellStyle(rawValue: cellType)!
            
            switch cell {
            case .Normal:
                let normal = UIBezierPath(roundedRect: self.viewMain.bounds, byRoundingCorners: [.bottomLeft, .bottomRight], cornerRadii: CGSize(width: 0, height: 0))
                
                maskLayer.path = normal.cgPath
                self.viewMain.layer.mask = maskLayer
            case .Rounded:
                let rounded = UIBezierPath(roundedRect: self.viewMain.bounds, byRoundingCorners: [.bottomLeft, .bottomRight], cornerRadii: CGSize(width: 10, height: 10))
                
                maskLayer.path = rounded.cgPath
                self.viewMain.layer.mask = maskLayer
            }
        }
    }
}

在您的ViewController-> cellForRowAt中-在主队列上调用以下代码

DispatchQueue.main.async {
            if totalRows == index + 1 { //write your condition
                cell.cellType = cellStyle.Rounded.rawValue
            } else {
                cell.cellType = cellStyle.Normal.rawValue
            }
            cell.layoutSubviews()
            cell.layoutIfNeeded()
        }

答案 6 :(得分:0)

这对我有用:

view.clipsToBounds = true
view.layer.cornerRadius = value
view.layer.maskedCorners = [.layerMaxXMaxYCorner, .layerMinXMaxYCorner]

答案 7 :(得分:0)

根据我的经验,这是让动态大小的图层正常工作的方法。

//Inside the cell or the view class
override func layoutSublayers(of layer: CALayer) {
    super.layoutSublayers(of: layer)
    
    if layer === self.layer {
        //Do any dynamic-layer update here
        myViewToRound.layer.cornerRadius = myViewToRound.bounds.width/2
    }
}

在这里,将 myViewToRound 替换为您希望在单元格/视图内四舍五入的 UIView 子类