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

后端 未结 26 2960
佛祖请我去吃肉
佛祖请我去吃肉 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:06

    In Swift 4.1 and Xcode 9.4.1

    In iOS 11 this single line is enough:

    detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]//Set your view here
    

    See the complete code:

    //In viewDidLoad
    if #available(iOS 11.0, *) {
            detailsSubView.clipsToBounds = false
            detailsSubView.layer.cornerRadius = 10
            detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
    } else {
          //For lower versions
    }
    

    But for lower versions

    let rectShape = CAShapeLayer()
        rectShape.bounds = detailsSubView.frame
        rectShape.position = detailsSubView.center
        rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds,    byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath
        detailsSubView.layer.mask = rectShape
    

    Complete code is.

    if #available(iOS 11.0, *) {
        detailsSubView.clipsToBounds = false
        detailsSubView.layer.cornerRadius = 10
        detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
    } else {
        let rectShape = CAShapeLayer()
        rectShape.bounds = detailsSubView.frame
        rectShape.position = detailsSubView.center
        rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds,    byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath
        detailsSubView.layer.mask = rectShape
    }
    

    If you are using AutoResizing in storyboard write this code in viewDidLayoutSubviews().

    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
    
        if #available(iOS 11.0, *) {
            detailsSubView.clipsToBounds = false
            detailsSubView.layer.cornerRadius = 10
            detailsSubView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
        } else {
            let rectShape = CAShapeLayer()
            rectShape.bounds = detailsSubView.frame
            rectShape.position = detailsSubView.center
            rectShape.path = UIBezierPath(roundedRect: detailsSubView.bounds,    byRoundingCorners: [.topLeft , .topRight], cornerRadii: CGSize(width: 20, height: 20)).cgPath
            detailsSubView.layer.mask = rectShape
        }
    }
    
    0 讨论(0)
  • 2020-11-22 07:09

    This would be the simplest answer:

    yourView.layer.cornerRadius = 8
    yourView.layer.masksToBounds = true
    yourView.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
    
    0 讨论(0)
  • 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.

    0 讨论(0)
  • 2020-11-22 07:11

    iOS 11 , Swift 4
    And you can try this code:

    if #available(iOS 11.0, *) {
       element.clipsToBounds = true
       element.layer.cornerRadius = CORNER_RADIUS
       element.layer.maskedCorners = [.layerMaxXMaxYCorner]
    } else {
       // Fallback on earlier versions
    }
    

    And you can using this in table view cell.

    0 讨论(0)
  • 2020-11-22 07:13

    Another version of Stephane's answer.

    import UIKit
    
        class RoundCornerView: UIView {
        var corners : UIRectCorner = [.topLeft,.topRight,.bottomLeft,.bottomRight]
            var roundCornerRadius : CGFloat = 0.0
            override func layoutSubviews() {
                super.layoutSubviews()
                if corners.rawValue > 0 && roundCornerRadius > 0.0 {
                    self.roundCorners(corners: corners, radius: roundCornerRadius)
                }
            }
            private func roundCorners(corners: UIRectCorner, radius: CGFloat) {
                let path = UIBezierPath(roundedRect: bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
                let mask = CAShapeLayer()
                mask.path = path.cgPath
                layer.mask = mask
            }
    
        }
    
    0 讨论(0)
  • 2020-11-22 07:14

    My solution for rounding specific corners of UIView and UITextFiels in swift is to use

    .layer.cornerRadius

    and

    layer.maskedCorners

    of actual UIView or UITextFields.

    Example:

    fileprivate func inputTextFieldStyle() {
            inputTextField.layer.masksToBounds = true
            inputTextField.layer.borderWidth = 1
            inputTextField.layer.cornerRadius = 25
            inputTextField.layer.maskedCorners = [.layerMaxXMaxYCorner,.layerMaxXMinYCorner]
            inputTextField.layer.borderColor = UIColor.white.cgColor
        }
    

    And by using

    .layerMaxXMaxYCorner

    and

    .layerMaxXMinYCorner

    , I can specify top right and bottom right corner of the UITextField to be rounded.

    You can see the result here:

    0 讨论(0)
提交回复
热议问题