skip to Main Content

I am trying to round the top two corners of a UIView and add a shadow above this view using a UIView extension. However the solution I came up with isn’t working. When I use the following solution the shadow only appears in the rounded corners and not above the view where I want it.

extension UIView {
    
    func roundCornersWithShadow(_ corners: UIRectCorner, radius: CGFloat) {
        let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
        let mask = CAShapeLayer()
        layer.mask = mask
        mask.path = path.cgPath
        mask.shadowColor = UIColor.black.cgColor
        mask.shadowPath = mask.path
        mask.shadowOffset = CGSize(width: 0.0, height: -2.0)
        mask.shadowOpacity = 0.9
        mask.shadowRadius = 3
        layer.masksToBounds = false
    }
}

4

Answers


  1. Chosen as BEST ANSWER

    SWIFT 5: iOS 11 introduced maskedCorners which results in smoother and better quality results. You can still use the UIRectCorner in the function call and have it translated to CACornerMask:

    extension UIView {
    
        func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
            if #available(iOS 11.0, *) {
                clipsToBounds = true
                layer.cornerRadius = radius
                layer.maskedCorners = CACornerMask(rawValue: corners.rawValue)
            } else {
                let path = UIBezierPath(
                    roundedRect: bounds, 
                    byRoundingCorners: corners, 
                    cornerRadii: CGSize(width: radius, height: radius)
                )
                let mask = CAShapeLayer()
                mask.path = path.cgPath
                layer.mask = mask
            }
        }
    
        func addShadow(shadowColor: CGColor = UIColor.label.cgColor,
                       shadowOffset: CGSize = CGSize(width: 1.0, height: 2.0),
                       shadowOpacity: Float = 0.4,
                       shadowRadius: CGFloat = 3.0) {
            self.layer.shadowColor = shadowColor
            self.layer.shadowOffset = shadowOffset
            self.layer.shadowOpacity = shadowOpacity
            self.layer.shadowRadius = shadowRadius
            self.layer.masksToBounds = false
        }
    }
    

    These functions need to be applied in layoutSubviews() of your superview.

    override func layoutSubviews() {
         roundCorners([.topLeft, .topRight], radius: 15)
         addShadow(shadowColor: UIColor.text1.cgColor, shadowOffset: CGSize(width: 0, height: -3), shadowOpacity: 0.2, shadowRadius: 5)
    }
    

  2. //must be used layoutSubviews inside . 
    override func layoutSubviews() {
        super.layoutSubviews()
        backView.round(corners: [.topLeft,.topRight], radius: 40)
    }
    
    Login or Signup to reply.
  3. [SWIFT-5] iOS 11 introduced maskedCorners which results in smoother and better quality results. You can still use the UIRectCorner in the function call and have it translated to CACornerMask:

    extension UIView {
    
    func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
        if #available(iOS 11.0, *) {
            clipsToBounds = true
            layer.cornerRadius = radius
            layer.maskedCorners = CACornerMask(rawValue: corners.rawValue)
        } else {
            let path = UIBezierPath(
                roundedRect: bounds, 
                byRoundingCorners: corners, 
                cornerRadii: CGSize(width: radius, height: radius)
            )
            let mask = CAShapeLayer()
            mask.path = path.cgPath
            layer.mask = mask
        }
    }
    

    }

    Login or Signup to reply.
  4. You can use this extension:

    extension UIView {
    
        /// Rounds ``UIView`` corners.
        /// - Parameters:
        ///   - maskedCorners: Corners to be rounded.
        ///   - cornerRadius: Value to be set as corner radius.
        func roundCorners(maskedCorners: CACornerMask = [.layerMinXMinYCorner, .layerMaxXMinYCorner],
                          cornerRadius: CGFloat = roundedCornersRadius) {
            layer.cornerRadius = cornerRadius
            layer.maskedCorners = maskedCorners
            layer.masksToBounds = true
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search