Create sketch type shadow - ios

I created a sketch design with shadows but when i tried implementing this in Xcode with swift i am not getting my desired result this is what i want to achieve
But this is what i keep getting
Here is the code i am using
extension CALayer {
func applySketchShadow(
color: UIColor = .black,
alpha: Float = 0.5,
x: CGFloat = 0,
y: CGFloat = 2,
blur: CGFloat = 4,
spread: CGFloat = 0)
{
shadowColor = color.cgColor
shadowOpacity = alpha
shadowOffset = CGSize(width: x, height: y)
shadowRadius = blur / 2.0
if spread == 0 {
shadowPath = nil
} else {
let dx = -spread
let rect = bounds.insetBy(dx: dx, dy: dx)
shadowPath = UIBezierPath(rect: rect).cgPath
}
}
}

You only need to do is that you have to increase the value of y.
If you set the value of x and y to 0.0, then it will show the shadow like box. So, when you increase the value of y then the shadow will move to down side. So, you will not see the shadow upside and it looks like what you need.
Hope this will help you.

Related

Swift - drop shadow on the masked image in the table row

here is a situation.
I've created a storyboard and UIViewController. To UIViewController I've added UITableView. To UITableView I've registered custom TableViewCell in which I need to add a rounded image and drop shadow from it.
I've created UIView and added to it UIImageView. For UIView I've created file with the following code:
class drawView: UIView {
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else {
return
}
self.drawCircle(context)
}
private func drawCircle(_ context: CGContext){
context.setStrokeColor(UIColor.black.cgColor)
let newMask = CAShapeLayer()
let circlePath = UIBezierPath(ovalIn: .init(x: 0, y: 0, width: 50, height: 50))
newMask.path = circlePath.cgPath
self.layer.mask = newMask //if I comment this line then the shadows works properly, if not, there is no shadows
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOpacity = 0.5
self.layer.shadowOffset = .init(width: 10, height: -10)
self.layer.shadowRadius = 2
}
}
How can I make rounded image and rounded shadow from it in the table row?
Thanks in advance for help.
I made some extensions, check this:
extension UIView {
/// Apply corder radius to the view
/// - parameter radius: The corder radius value applied to view. Default value: 4
func makeRoundCorner(withRadius radius: CGFloat = 4) {
clipsToBounds = true
layer.cornerRadius = radius
}
/// Apply shadow to the view
/// - parameter offset: The offset (in points) of the layer’s shadow. Default value: CGSize(width: 0, height: 2)
/// - parameter opacity: The opacity of the layer’s shadow. Default value: 0.2
/// - parameter radius: The blur radius (in points) used to render the layer’s shadow. Default value: 4
/// - parameter color: The color of the layer’s shadow. Default value: opaque black
func makeShadow(offset: CGSize = CGSize(width: 0, height: 2),
opacity: Float = 0.2,
radius: CGFloat = 4,
color: UIColor = UIColor.black) {
let layer = self.layer
layer.shadowColor = color.cgColor
layer.shadowOffset = offset
layer.shadowRadius = radius
layer.shadowOpacity = opacity
clipsToBounds = false
}
}
How to use and the output
let image = UIImageView(image: UIImage(named: "test_icon"))
image.backgroundColor = .red
image.makeRoundCorner(withRadius: 20)
image.makeShadow(offset: CGSize(width: 1, height: 1), opacity: 1, radius: 4, color: .black)

Correctly setting corner radius to Rects drawn with Gore Graphics

I want to implement a bar constisting of colored rectangles to visualise a distribution, similar to the storage graphic on the iPhone.
My current approach is this, which is working correctly:
override open func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
drawRects(context!)
}
func drawRects(_ context:CGContext) {
if values.count == 0 { return }
var currentX: Float = 0
let scale = (Float(self.frame.width)) / Float(totalSum)
for i in 0..<values.count {
let color = colors[i].cgColor
let value = values[i]
let rect = CGRect(x: CGFloat(currentX), y: 0, width: CGFloat(Float(value) * scale), height: frame.size.height)
context.addRect(rect)
context.setFillColor(color)
context.fill(rect)
currentX += ((Float(value) * scale) + (value == 0 ? 0 : barSpacing))
}
}
The result is this:
Now I want to round the edges of the individual rectangles with UIBezierPath using this code at the end of the for-loop in the drawRects method:
let path = UIBezierPath(roundedRect: rect, cornerRadius: rect.height / 2)
UIColor.white.setStroke()
path.stroke()
This leads to this:
Somehow this doesn't just round the edges, but cuts off a bit of the height and width, which leads to the small leftovers of the rectangle in the corners. As you can see in the two images, the height of the rectangles changes when applying the path.
Setting the UIBezierPath as a path to the current Core Graphics context instead of setting it as a stroke leads to the same problem.
What is it that I'm doing wrong?
Disclaimer: Did this without testing.
I do believe the way you are filling in your context is incorrect. So, you are filling via context.fill(rect), which does exactly as you are stating. Fill the rect, everything except the path. Well, the path doesn't interfere with the corner, thus your result.
To counter this, we utilize the method context.fillPath() which provides the default rule, CGPathFillRule = .winding. It should only fill the interior of the `rect.
https://developer.apple.com/documentation/coregraphics/cgpathfillrule
CGPathFillRule: When filling a path, regions that a fill rule defines as interior to the path are painted. When clipping with a path, regions interior to the path remain visible after clipping.
override open func draw(_ rect: CGRect) {
let context = UIGraphicsGetCurrentContext()
drawRects(context!)
}
func drawRects(_ context:CGContext) {
if values.count == 0 { return }
var currentX: Float = 0
let scale = (Float(self.frame.width)) / Float(totalSum)
for i in 0..<values.count {
let color = colors[i].cgColor
let value = values[i]
let rect = CGRect(x: CGFloat(currentX), y: 0, width: CGFloat(Float(value) * scale), height: frame.size.height)
let path = UIBezierPath(roundedRect: rect, cornerRadius: rect.height / 2)
context.addPath(path.cgPath)
context.addRect(rect)
context.setFillColor(color)
context.fillPath()
context.closePath()
currentX += ((Float(value) * scale) + (value == 0 ? 0 : barSpacing))
}
}
The solution that finally worked for me is to fill the UIBezierPath, rather than the rectangle:
let rect = CGRect(x: CGFloat(currentX), y: 0, width: CGFloat(Float(value) * scale), height: frame.size.height)
let path = UIBezierPath(roundedRect: rect, cornerRadius: rect.height / 2)
context.setFillColor(color)
path.fill()

Tableview Xib Shadow Swift

Here is what I am trying to do:
The screenshot is taken from Iphone:
This is my code:
cell.shadowLayerView.layer.masksToBounds = false
cell.shadowLayerView.layer.shadowOffset = CGSize(width: 0, height: 0)
cell.shadowLayerView.layer.shadowColor = UIColor.black.cgColor
cell.shadowLayerView.layer.shadowOpacity = 0.23
cell.shadowLayerView.layer.shadowRadius = 4
cell.shadowLayerView.layer.shadowPath = UIBezierPath(roundedRect: cell.shadowLayerView.bounds, cornerRadius: 2).cgPath
cell.shadowLayerView.layer.shouldRasterize = true
cell.shadowLayerView.layer.rasterizationScale = UIScreen.main.scale
cell.discriptionLbl.frame.size.width = UIScreen.main.bounds.size.width
This is my tableview xib. In original image show light gray color shadow all side(Top,Bottom,left,Right) but in taken image show all side shadow but why show extra shadow in right side and bottom side.
See Below Image:
Question: How to show same shadow from all side of the view like original image(shadow in light gray color)?
Can someone please explain to me how to solve this , i've tried to solve this issue but no results yet.
Any help would be greatly appreciated.
Thanks in advance.
See the below code:
mainViewCorner.layer.shadowColor = UIColor.red.cgColor;
mainViewCorner.layer.shadowOffset = CGSize.zero //direction of shadow
mainViewCorner.layer.shadowOpacity = 1.0; // opacity for shadow
mainViewCorner.layer.shadowRadius = 0.0; //amount of shadow to blur
mainViewCorner.layer.cornerRadius = 4.0;
issue with your code was shadowOffset. It defines the direction of your shadow. If you want shadow on all sides - it must have zero value for both width and height.
try it
myView.layer.cornerRadius = 10
let shadowPath = UIBezierPath(roundedRect: myView.bounds, cornerRadius: 10)
myView.layer.masksToBounds = false
myView.layer.shadowColor = UIColor.gray.cgColor
myView.layer.shadowOffset = CGSize(width: 0, height: 2)
myView.layer.shadowOpacity = 0.5
Or you can use Sketch Shadow
extension CALayer {
func applySketchShadow(
color: UIColor = .black,
alpha: Float = 0.5,
x: CGFloat = 0,
y: CGFloat = 2,
blur: CGFloat = 4,
spread: CGFloat = 0)
{
shadowColor = color.cgColor
shadowOpacity = alpha
shadowOffset = CGSize(width: x, height: y)
shadowRadius = blur / 2.0
if spread == 0 {
shadowPath = nil
} else {
let dx = -spread
let rect = bounds.insetBy(dx: dx, dy: dx)
shadowPath = UIBezierPath(rect: rect).cgPath
}
}
}
apply Sketch Shadow
myView.layer.cornerRadius = 10
let shadowPath = UIBezierPath(roundedRect: myView.bounds, cornerRadius: 10)
myView.layer.applySketchShadow(
color: .black,
alpha: 0.5,
x: CGFloat(0),
y: CGFloat(10),
blur: 20,
spread: 0)
myView.layer.shadowPath = shadowPath.cgPath

Set Shadow on Bottom UIView only

I want to create bottom only shadow on UIView. Right now with this function, will create shadow in top, bottom, left, and right.
func setCardView(view : UIView){
view.layer.masksToBounds = false
view.layer.shadowOffset = CGSize(width: 0, height: 0)
view.layer.shadowRadius = 2
view.layer.shadowOpacity = 0.5
}
Is there anyway to only create shadow in the bottom?
Any help would be appreciated. Thank you!
I think the proper way of thinking of shadow is, the shadow belongs to the object, which is the button, the uiview, not just part of the side. Imagining there is a virtual light source. You can't really just create a shadow for one side.
With that being said, the shadow will always be the shadow of the view as a whole. However, you can change the shadow offset to make it towards to the bottom.
view.layer.shadowOffset = CGSize(width: 0, height: 3)
This means you want the light source shoot the light from top to make the shadow to the bottom. The reason you still see some shadow at the top is the shadow radius. which is to simulate the diffuse of the light. The more diffuse the light is, the softer the shadow will be so you will see top shadow still.
view.layer.shadowRadius = 1 or 0.5
try to reduce the radius also. it will give you a better visual result.
To understand umbra, penumbra and antumbra if you need, check out https://en.wikipedia.org/wiki/Umbra,_penumbra_and_antumbra
This adds a shadow only to bottom. Implemented as an extension to UIView
extension UIView {
func addBottomShadow() {
layer.masksToBounds = false
layer.shadowRadius = 4
layer.shadowOpacity = 1
layer.shadowColor = UIColor.gray.cgColor
layer.shadowOffset = CGSize(width: 0 , height: 2)
layer.shadowPath = UIBezierPath(rect: CGRect(x: 0,
y: bounds.maxY - layer.shadowRadius,
width: bounds.width,
height: layer.shadowRadius)).cgPath
}
}
This code working for swift 4 and shadow applying for view Bottom:
view.layer.masksToBounds = false
view.layer.shadowRadius = 4
view.layer.shadowOpacity = 1
view.layer.shadowColor = UIColor.gray.cgColor
view.layer.shadowOffset = CGSize(width: 0 , height:2)
If you really want a shadow only on one side of your UIView, you should set your view.layer.shadowPath to a UIBezierPath.
Here is an example which will only display a shadow at the bottom of the view:
view.layer.shadowPath = UIBezierPath(rect: CGRect(x: 0,
y: bounds.maxY - layer.shadowRadius,
width: bounds.width,
height: layer.shadowRadius)).cgPath
Deconstructing the CGRect value, you get:
x and width make sure the shadow takes the full horizontal width of your view (you might want to adjust them, for example using the layer.shadowRadius value as a basis for your offsetting)
y and height make sure the shadow starts as low as possible and then is only as big as the radius
Of course, there are some cases where this won't work, for example when you want a shadowRadius larger than your view's height. In these cases, I would recommend using an image view or a masked layer.
Hope this helps,
Change your shadowOffset
view.layer.shadowOffset = CGSize(width: 0, height: 3)
Here's the proper way of applying shadow in Swift:
yourView.layer.shadowOffset = CGSize(width: 0, height: 3)
yourView.layer.shadowOpacity = 0.6
yourView.layer.shadowRadius = 3.0
yourView.layer.shadowColor = UIColor.red.cgColor
Old question but it seems none of the answers really answer the question.
While the above answers will work with a low shadowRadius you don't really get a 'shadow' effect.
You can absolutely add a shadow to just the bottom by using UIBezierPath
Heres how -
let shadowWidth: CGFloat = 1.2 // Shadow width, will be the width furthest away from the view, this is equivalent to 120% of the views width
let shadowHeight: CGFloat = 0.3 // Shadow height, again this is equivalent to 30%
let shadowRadius: CGFloat = 5
let width = someView.frame.width
let height = someView.frame.height // Get width and height of the view
// Plot the path
let shadowPath = UIBezierPath()
shadowPath.move(to: CGPoint(x: shadowRadius / 2, y: height - shadowRadius / 2))
shadowPath.addLine(to: CGPoint(x: width - shadowRadius / 2, y: height - shadowRadius / 2))
shadowPath.addLine(to: CGPoint(x: width * shadowWidth, y: height + (height * shadowHeight)))
shadowPath.addLine(to: CGPoint(x: width * -(shadowWidth - 1), y: height + (height * shadowHeight)))
// Add shadow
someView.layer.shadowPath = shadowPath.cgPath
someView.layer.shadowRadius = shadowRadius
someView.layer.shadowOffset = .zero
someView.layer.shadowOpacity = 0.2
This outputs this
Or if you wanted a simpler solution, with less options you could go with this
let buttonHeight = someButton.frame.height
let buttonWidth = someButton.frame.width
let shadowSize: CGFloat = 15
let contactRect = CGRect(x: -shadowSize, y: buttonHeight - (shadowSize * 0.2), width: buttonWidth + shadowSize * 2, height: shadowSize)
someButton.layer.shadowPath = UIBezierPath(ovalIn: contactRect).cgPath
someButton.layer.shadowRadius = 5
someButton.layer.shadowOpacity = 0.6
Which will output this
Example here
https://github.com/hemo87/ExampleShadow/tree/master
class ViewBottomShadow: UIView {
init() {
super.init(frame: .zero)
backgroundColor = .white
layer.masksToBounds = false
layer.shadowRadius = 2
layer.shadowOpacity = 1
layer.shadowColor = UIColor.gray.cgColor
layer.shadowOffset = CGSize(width: 0 , height:2)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Just draw regular shadow and rotate it upside down, as simple as that
#objc func shadowView() -> UIView {
let shadowView = UIView(frame: .zero)
shadowView.backgroundColor = .white
shadowView.layer.shadowColor = UIColor.grey.cgColor
shadowView.layer.shadowOffset = CGSize(width: 0, height: 2)
shadowView.layer.shadowOpacity = 1.0
shadowView.layer.shadowRadius = 4
shadowView.layer.compositingFilter = "multiplyBlendMode"
return shadowView
}
func idtm_addBottomShadow() {
let shadow = shadowView()
shadow.transform = transform.rotated(by: 180 * CGFloat(Double.pi))
shadow.transform = transform.rotated(by: -1 * CGFloat(Double.pi))
shadow.translatesAutoresizingMaskIntoConstraints = false
addSubview(shadow)
NSLayoutConstraint.activate([
shadow.leadingAnchor.constraint(equalTo: leadingAnchor),
shadow.trailingAnchor.constraint(equalTo: trailingAnchor),
shadow.bottomAnchor.constraint(equalTo: bottomAnchor),
shadow.heightAnchor.constraint(equalToConstant: 1),
])
}

How to control shadow spread and blur?

I have designed UI elements in sketch, and one of them has a shadow with blur 1 and spread 0. I looked at the doc for the views layer property and layer doesn't have anything named spread or blur, or anything equivalent (the only control was merely shadowOpacity). How can control things like blur and spread?
Here are my settings in Sketch:
And here is what I want my shadow to look like:
And here is what it looks like at the moment:
Note, you have to click on the picture to actually see the shadow.
My code is as follows:
func setupLayer(){
view.layer.cornerRadius = 2
view.layer.shadowColor = Colors.Shadow.CGColor
view.layer.shadowOffset = CGSize(width: 0, height: 1)
view.layer.shadowOpacity = 0.9
view.layer.shadowRadius = 5
}
Here's how to apply all 6 Sketch shadow properties to a UIView's layer with near perfect accuracy:
extension CALayer {
func applySketchShadow(
color: UIColor = .black,
alpha: Float = 0.5,
x: CGFloat = 0,
y: CGFloat = 2,
blur: CGFloat = 4,
spread: CGFloat = 0)
{
masksToBounds = false
shadowColor = color.cgColor
shadowOpacity = alpha
shadowOffset = CGSize(width: x, height: y)
shadowRadius = blur / 2.0
if spread == 0 {
shadowPath = nil
} else {
let dx = -spread
let rect = bounds.insetBy(dx: dx, dy: dx)
shadowPath = UIBezierPath(rect: rect).cgPath
}
}
}
Say we want to represent the following:
You can easily do this via:
myView.layer.applySketchShadow(
color: .black,
alpha: 0.5,
x: 0,
y: 0,
blur: 4,
spread: 0)
or more succinctly:
myView.layer.applySketchShadow(y: 0)
Example:
Left: iPhone 8 UIView screenshot; right: Sketch rectangle.
Note:
When using a non-zero spread, it hardcodes a path based on the bounds of the CALayer. If the layer's bounds ever change, you'd want to call the applySketchShadow() method again.
You can try this .... you can play with the values.
The shadowRadius dictates the amount of blur. shadowOffset dictates where the shadow goes.
Swift 2.0
let radius: CGFloat = demoView.frame.width / 2.0 //change it to .height if you need spread for height
let shadowPath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 2.1 * radius, height: demoView.frame.height))
//Change 2.1 to amount of spread you need and for height replace the code for height
demoView.layer.cornerRadius = 2
demoView.layer.shadowColor = UIColor.blackColor().CGColor
demoView.layer.shadowOffset = CGSize(width: 0.5, height: 0.4) //Here you control x and y
demoView.layer.shadowOpacity = 0.5
demoView.layer.shadowRadius = 5.0 //Here your control your blur
demoView.layer.masksToBounds = false
demoView.layer.shadowPath = shadowPath.CGPath
Swift 3.0
let radius: CGFloat = demoView.frame.width / 2.0 //change it to .height if you need spread for height
let shadowPath = UIBezierPath(rect: CGRect(x: 0, y: 0, width: 2.1 * radius, height: demoView.frame.height))
//Change 2.1 to amount of spread you need and for height replace the code for height
demoView.layer.cornerRadius = 2
demoView.layer.shadowColor = UIColor.black.cgColor
demoView.layer.shadowOffset = CGSize(width: 0.5, height: 0.4) //Here you control x and y
demoView.layer.shadowOpacity = 0.5
demoView.layer.shadowRadius = 5.0 //Here your control your blur
demoView.layer.masksToBounds = false
demoView.layer.shadowPath = shadowPath.cgPath
Example with spread
To create a basic shadow
demoView.layer.cornerRadius = 2
demoView.layer.shadowColor = UIColor.blackColor().CGColor
demoView.layer.shadowOffset = CGSizeMake(0.5, 4.0); //Here your control your spread
demoView.layer.shadowOpacity = 0.5
demoView.layer.shadowRadius = 5.0 //Here your control your blur
Basic Shadow example in Swift 2.0
Sketch Shadow Using IBDesignable and IBInspectable in Swift 4
SKETCH AND XCODE SIDE BY SIDE
CODE
#IBDesignable class ShadowView: UIView {
#IBInspectable var shadowColor: UIColor? {
get {
if let color = layer.shadowColor {
return UIColor(cgColor: color)
}
return nil
}
set {
if let color = newValue {
layer.shadowColor = color.cgColor
} else {
layer.shadowColor = nil
}
}
}
#IBInspectable var shadowOpacity: Float {
get {
return layer.shadowOpacity
}
set {
layer.shadowOpacity = newValue
}
}
#IBInspectable var shadowOffset: CGPoint {
get {
return CGPoint(x: layer.shadowOffset.width, y:layer.shadowOffset.height)
}
set {
layer.shadowOffset = CGSize(width: newValue.x, height: newValue.y)
}
}
#IBInspectable var shadowBlur: CGFloat {
get {
return layer.shadowRadius
}
set {
layer.shadowRadius = newValue / 2.0
}
}
#IBInspectable var shadowSpread: CGFloat = 0 {
didSet {
if shadowSpread == 0 {
layer.shadowPath = nil
} else {
let dx = -shadowSpread
let rect = bounds.insetBy(dx: dx, dy: dx)
layer.shadowPath = UIBezierPath(rect: rect).cgPath
}
}
}
}
OUTPUT
HOW TO USE IT
This code worked very well for me:
yourView.layer.shadowOpacity = 0.2 // opacity, 20%
yourView.layer.shadowColor = UIColor.black.cgColor
yourView.layer.shadowRadius = 2 // HALF of blur
yourView.layer.shadowOffset = CGSize(width: 0, height: 2) // Spread x, y
yourView.layer.masksToBounds = false
For those who are attempting to apply a shadow to a predefined path (Like for a circular view, for instance), here's what I ended up with:
extension CALayer {
func applyShadow(color: UIColor = .black,
alpha: Float = 0.5,
x: CGFloat = 0,
y: CGFloat = 2,
blur: CGFloat = 4,
spread: CGFloat = 0,
path: UIBezierPath? = nil) {
shadowColor = color.cgColor
shadowOpacity = alpha
shadowRadius = blur / 2
if let path = path {
if spread == 0 {
shadowOffset = CGSize(width: x, height: y)
} else {
let scaleX = (path.bounds.width + (spread * 2)) / path.bounds.width
let scaleY = (path.bounds.height + (spread * 2)) / path.bounds.height
path.apply(CGAffineTransform(translationX: x + -spread, y: y + -spread).scaledBy(x: scaleX, y: scaleY))
shadowPath = path.cgPath
}
} else {
shadowOffset = CGSize(width: x, height: y)
if spread == 0 {
shadowPath = nil
} else {
let dx = -spread
let rect = bounds.insetBy(dx: dx, dy: dx)
shadowPath = UIBezierPath(rect: rect).cgPath
}
}
shouldRasterize = true
rasterizationScale = UIScreen.main.scale
}
}
I'll post some examples later, but this has worked spot on for circular views for me.
My solution based on this post replies: (Swift 3)
let shadowPath = UIBezierPath(rect: CGRect(x: -1,
y: -2,
width: target.frame.width + 2,
height: target.frame.height + 2))
target.layer.shadowColor = UIColor(hexString: shadowColor).cgColor
target.layer.shadowOffset = CGSize(width: CGFloat(shadowOffsetX), height: CGFloat(shadowOffsetY))
target.layer.masksToBounds = false
target.layer.shadowOpacity = Float(shadowOpacity)
target.layer.shadowPath = shadowPath.cgPath
Change a little bit from #Senseful 's answer and works fine to my project.
Support shadow corner radius (for some round corner view)
spread == 0 it still apply shadow effect(looks like border)
struct SketchShadow {
var color: UIColor = .black
let alpha: Float = 0.1
let x: CGFloat
let y: CGFloat
let blur: CGFloat
let spread: CGFloat
let cornorRadius: CGFloat
func applyToLayer(_ layer: CALayer) {
layer.masksToBounds = false
layer.shadowColor = color.cgColor
layer.shadowOpacity = alpha
layer.shadowOffset = CGSize(width: x, height: y)
layer.shadowRadius = blur / 2.0
if spread == 0 {
layer.shadowPath = UIBezierPath(roundedRect: layer.bounds, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: cornorRadius, height: cornorRadius)).cgPath
} else {
let dx = -(spread)
let rect = layer.bounds.insetBy(dx: dx, dy: dx)
layer.shadowPath = UIBezierPath(roundedRect: rect, byRoundingCorners: .allCorners, cornerRadii: CGSize(width: cornorRadius, height: cornorRadius)).cgPath
}
}
}
I really like the answer posted here and suggestions in the comments. This is how I modified that solution:
extension UIView {
func applyShadow(color: UIColor, alpha: Float, x: CGFloat, y: CGFloat, blur: CGFloat, spread: CGFloat) {
layer.masksToBounds = false
layer.shadowColor = color.cgColor
layer.shadowOpacity = alpha
layer.shadowOffset = CGSize(width: x, height: y)
layer.shadowRadius = blur / UIScreen.main.scale
if spread == 0 {
layer.shadowPath = nil
} else {
let dx = -spread
let rect = bounds.insetBy(dx: dx, dy: dx)
layer.shadowPath = UIBezierPath(rect: rect).cgPath
}
}
}
USAGE:
myButton.applyShadow(color: .black, alpha: 0.2, x: 0, y: 1, blur: 2, spread: 0)
It might be a little diggin in history, but maybe some had same issue. I useed code sample from accepted answer. However the effects are quite different:
- y value has to be around half compared to same value in sketch
- I tried to apply shadow on navigation bar and the effect is terribly different - barely visible while using same values that sketch had.
So there seems that the method is totally not reflecting sketch parameters.
Any hints?

Resources