UIBezierPath:roundedRect:byRoundingCorners:cornerRadii:行为怪异

时间:2015-08-10 15:43:51

标签: ios uibezierpath rounded-corners cashapelayer

我正试图让按钮的两个角落成圆形。如果我像这样选择.TopLeft和.BottomLeft:

let bezierDisableAdsPath = UIBezierPath(roundedRect: disableAdsButton.bounds, byRoundingCorners: [UIRectCorner.TopLeft , UIRectCorner.BottomLeft] , cornerRadii: CGSizeMake(4.0, 4.0))

        let maskAdsLayer = CAShapeLayer()
        maskAdsLayer.frame = disableAdsButton.bounds
        maskAdsLayer.path = bezierDisableAdsPath.CGPath
        disableAdsButton.layer.mask = maskAdsLayer

比代码工作得非常好。

如果我选择.TopRight和。 BottomRight是这样的:

let bezierDisableAdsPath = UIBezierPath(roundedRect: disableAdsButton.bounds, byRoundingCorners: [UIRectCorner.TopRight , UIRectCorner.BottomRight] , cornerRadii: CGSizeMake(4.0, 4.0))

        let maskAdsLayer = CAShapeLayer()
        maskAdsLayer.frame = disableAdsButton.bounds
        maskAdsLayer.path = bezierDisableAdsPath.CGPath
        disableAdsButton.layer.mask = maskAdsLayer

比我看不到圆角。这是怎么回事?

我已经尝试将maskAdsLayer添加为子视图,但它不起作用。

2 个答案:

答案 0 :(得分:3)

如果您在viewDidLoad中执行此操作,此时可能尚未应用自动布局约束,因此按钮的框架可能未达到其最终值,因此disableAdsButton.bounds可能不是你期望的那样。因此,向右倒圆的角可能不可见。您可以通过在此代码运行的位置记录按钮的bounds来确认这一点,然后在布局视图后再次查看它。

您可以将此问题推迟到viewDidAppear或更好,viewDidLayoutSubviews

答案 1 :(得分:0)

找到这个答案后(感谢kickstart),并尝试了缺失的细节,这里是我的最终理解:

  • 该层只需要创建一次
  • 必须在视图的矩形更改时更新
  • 捕获的最佳位置是layoutSubviews()

我们可以使用为UIView设置自定义图层形状类的功能来封装它。首先,我们使用CAShapeLayer掩码定义我们自己的图层类:

class RoundedShapeLayer: CAShapeLayer {
  override init() {
    super.init()
    self.mask = CAShapeLayer()
  }    
  override init(layer: Any) {
    super.init(layer: layer)
    self.mask = CAShapeLayer()
  }    
  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    self.mask = CAShapeLayer()
  }

  func update(for bounds: CGRect) {
    (mask as! CAShapeLayer).path =
        UIBezierPath(roundedRect: bounds,
                     byRoundingCorners: [UIRectCorner.topRight, UIRectCorner.topLeft],
                     cornerRadii: CGSize(width: 10, height: 10)).cgPath

  }
}

然后我们可以在UIView中使用它:

@IBDesignable class RoundedCornerView: UIView {    
  override class var layerClass: AnyClass {
    get {
        return RoundedShapeLayer.self
    }
  }

  override init(frame: CGRect) {
    super.init(frame: frame)
  }

  required init?(coder: NSCoder) {
    super.init(coder: coder)
  }

  override func layoutSubviews() {
    super.layoutSubviews()
    (layer as! RoundedShapeLayer).update(for: bounds)
  }
}

还有更多的工作可以让角落定制,但这就是精神。