Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Swift - Problems with corner radius and drop shadow

I'm trying to create a button with rounded corners and a drop shadow. No matter how I switch up, the button will not display correctly. I've tried masksToBounds = false and masksToBounds = true, but either the corner radius works and the shadow does not or the shadow works and the corner radius doesn't clip the corners of the button.

import UIKit import QuartzCore  @IBDesignable class Button : UIButton {     @IBInspectable var masksToBounds: Bool    = false                {didSet{updateLayerProperties()}}     @IBInspectable var cornerRadius : CGFloat = 0                    {didSet{updateLayerProperties()}}     @IBInspectable var borderWidth  : CGFloat = 0                    {didSet{updateLayerProperties()}}     @IBInspectable var borderColor  : UIColor = UIColor.clearColor() {didSet{updateLayerProperties()}}     @IBInspectable var shadowColor  : UIColor = UIColor.clearColor() {didSet{updateLayerProperties()}}     @IBInspectable var shadowOpacity: CGFloat = 0                    {didSet{updateLayerProperties()}}     @IBInspectable var shadowRadius : CGFloat = 0                    {didSet{updateLayerProperties()}}     @IBInspectable var shadowOffset : CGSize  = CGSizeMake(0, 0)     {didSet{updateLayerProperties()}}      override func drawRect(rect: CGRect)     {         updateLayerProperties()     }      func updateLayerProperties()     {         self.layer.masksToBounds = masksToBounds         self.layer.cornerRadius = cornerRadius         self.layer.borderWidth = borderWidth         self.layer.borderColor = borderColor.CGColor         self.layer.shadowColor = shadowColor.CGColor         self.layer.shadowOpacity = CFloat(shadowOpacity)         self.layer.shadowRadius = shadowRadius         self.layer.shadowOffset = shadowOffset     } } 
like image 637
Jake Avatar asked Jul 09 '14 03:07

Jake


People also ask

How do I add inner shadow to UIView with rounded corners?

Add subview with the same color which will be centered on the parent and will be with several pixels smaller. Like this you will have space from each side of the parent. On the parent turn on clipping subviews and add shadow to the inner view. Like this, you can have an inner shadow.

How do you show corner radius in Swift?

You can give it round corners by changing the cornerRadius property of the view's layer . and smaller values give less rounded corners. Both clipsToBounds and masksToBounds are equivalent.

How to add shadow and corner radius to UIView using cashapelayer?

Using CAShapeLayer and UIBezierPath we can easily add shadow and corner radius to UIView and the class derived from it like UIButton, UIImageView, UILabel etc. We will add UIView Extension and the good point of this is, you only need to write just one line of code to achieve this.

Why doesn't my uivisualeffectview have rounded corners?

If you add something like a UIVisualEffectView as a subview to this view you likely need to use the same rounded corners on that UIVisualEffectView or it won't have rounded corners.

How do I set the corner radius of a UIView?

Implementing the @IBDesignable UIView extension and applying the @IBInspectable modifier to the cornerRadius property allows a view’s corner radius to be set in a Storyboard’s Attributes Inspector: Adding a shadow to a UIView can be implemented by setting the shadowColor, shadowOpacity, shadowOffset, and shadowRadius properties on the view’s layer:

How do I make a view have rounded corners?

Subclass your view from this and it should have rounded corners. If you add something like a UIVisualEffectView as a subview to this view you likely need to use the same rounded corners on that UIVisualEffectView or it won't have rounded corners.


2 Answers

The following Swift 5 / iOS 12 code shows how to set a subclass of UIButton that allows to create instances with rounded corners and shadow around it:

import UIKit  final class CustomButton: UIButton {      private var shadowLayer: CAShapeLayer!      override func layoutSubviews() {         super.layoutSubviews()          if shadowLayer == nil {             shadowLayer = CAShapeLayer()             shadowLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: 12).cgPath             shadowLayer.fillColor = UIColor.white.cgColor              shadowLayer.shadowColor = UIColor.darkGray.cgColor             shadowLayer.shadowPath = shadowLayer.path             shadowLayer.shadowOffset = CGSize(width: 2.0, height: 2.0)             shadowLayer.shadowOpacity = 0.8             shadowLayer.shadowRadius = 2              layer.insertSublayer(shadowLayer, at: 0)             //layer.insertSublayer(shadowLayer, below: nil) // also works         }             }  } 

According to your needs, you may add a UIButton in your Storyboard and set its class to CustomButton or you may create an instance of CustomButton programmatically. The following UIViewController implementation shows how to create and use a CustomButton instance programmatically:

import UIKit  class ViewController: UIViewController {      override func viewDidLoad() {         super.viewDidLoad()          let button = CustomButton(type: .system)         button.setTitle("Button", for: .normal)         view.addSubview(button)          button.translatesAutoresizingMaskIntoConstraints = false         let horizontalConstraint = button.centerXAnchor.constraint(equalTo: view.centerXAnchor)         let verticalConstraint = button.centerYAnchor.constraint(equalTo: view.centerYAnchor)                 let widthConstraint = button.widthAnchor.constraint(equalToConstant: 100)         let heightConstraint = button.heightAnchor.constraint(equalToConstant: 100)         NSLayoutConstraint.activate([horizontalConstraint, verticalConstraint, widthConstraint, heightConstraint])     }  } 

The previous code produces the image below in the iPhone simulator:

enter image description here

like image 102
Imanou Petit Avatar answered Sep 28 '22 04:09

Imanou Petit


My custom button with some shadow and rounded corners, I use it directly within the Storyboard with no need to touch it programmatically.

Swift 4

class RoundedButtonWithShadow: UIButton {     override func awakeFromNib() {         super.awakeFromNib()         self.layer.masksToBounds = false         self.layer.cornerRadius = self.frame.height/2         self.layer.shadowColor = UIColor.black.cgColor         self.layer.shadowPath = UIBezierPath(roundedRect: self.bounds, cornerRadius: self.layer.cornerRadius).cgPath         self.layer.shadowOffset = CGSize(width: 0.0, height: 3.0)         self.layer.shadowOpacity = 0.5         self.layer.shadowRadius = 1.0     } } 

enter image description here

like image 29
scope Avatar answered Sep 28 '22 04:09

scope