How to set cornerRadius for only top-left and top-right corner of a UIView?

后端 未结 26 3286
佛祖请我去吃肉
佛祖请我去吃肉 2020-11-22 06:14

Is there a way to set cornerRadius for only top-left and top-right corner of a UIView?

I tried the following, but it end up not seeing the

26条回答
  •  轮回少年
    2020-11-22 07:10

    All of the answers already given are really good and valid (especially Yunus idea of using the mask property).

    However I needed something a little more complex because my layer could often change sizes which mean I needed to call that masking logic every time and this was a little bit annoying.

    I used swift extensions and computed properties to build a real cornerRadii property which takes care of auto updating the mask when layer is layed out.

    This was achieved using Peter Steinberg great Aspects library for swizzling.

    Full code is here:

    extension CALayer {
      // This will hold the keys for the runtime property associations
      private struct AssociationKey {
        static var CornerRect:Int8 = 1    // for the UIRectCorner argument
        static var CornerRadius:Int8 = 2  // for the radius argument
      }
    
      // new computed property on CALayer
      // You send the corners you want to round (ex. [.TopLeft, .BottomLeft])
      // and the radius at which you want the corners to be round
      var cornerRadii:(corners: UIRectCorner, radius:CGFloat) {
        get {
          let number = objc_getAssociatedObject(self, &AssociationKey.CornerRect)  as? NSNumber ?? 0
          let radius = objc_getAssociatedObject(self, &AssociationKey.CornerRadius)  as? NSNumber ?? 0
          return (corners: UIRectCorner(rawValue: number.unsignedLongValue), radius: CGFloat(radius.floatValue))
        }
        set (v) {
          let radius = v.radius
          let closure:((Void)->Void) = {
            let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: v.corners, cornerRadii: CGSize(width: radius, height: radius))
            let mask = CAShapeLayer()
            mask.path = path.CGPath
            self.mask = mask
          }
          let block: @convention(block) Void -> Void = closure
          let objectBlock = unsafeBitCast(block, AnyObject.self)
          objc_setAssociatedObject(self, &AssociationKey.CornerRect, NSNumber(unsignedLong: v.corners.rawValue), .OBJC_ASSOCIATION_RETAIN)
          objc_setAssociatedObject(self, &AssociationKey.CornerRadius, NSNumber(float: Float(v.radius)), .OBJC_ASSOCIATION_RETAIN)
          do { try aspect_hookSelector("layoutSublayers", withOptions: .PositionAfter, usingBlock: objectBlock) }
          catch _ { }
        }
      }
    }
    

    I wrote a simple blog post explaining this.

提交回复
热议问题