How to make a drop shadow effect on a label in Swift?
Asked Answered
C

7

41

I can't figure out how to code a drop shadow on a label. I have a score label that changes so just photoshopping text with shadows wont be possible. I need to code it so it automatically has a blurry shadow behind the text at all times. Can anyone come with some examples or help?


People saying this is a duplicate, the "duplicate" is about drop shadows on UIView, mine is about UILabel. It's not the same thing.

Calculate answered 12/7, 2017 at 15:57 Comment(1)
Have you looked at the shadowColor and shadowOffset properties of UILabel?Fussy
E
94

Give this a try - you can run it directly in a Playground page:

import UIKit
import PlaygroundSupport

let container = UIView(frame: CGRect(x: 0, y: 0, width: 600, height: 400))

container.backgroundColor = UIColor.lightGray

PlaygroundPage.current.liveView = container

var r = CGRect(x: 40, y: 40, width: 300, height: 60)

let label = UILabel(frame: r)
label.font = UIFont.systemFont(ofSize: 44.0)
label.textColor = .white
label.frame = r
label.text = "Hello Blur"

container.addSubview(label)

label.layer.shadowColor = UIColor.black.cgColor
label.layer.shadowRadius = 3.0
label.layer.shadowOpacity = 1.0
label.layer.shadowOffset = CGSize(width: 4, height: 4)
label.layer.masksToBounds = false

Play around with different values for the shadow Color, Opacity, Radius and Offset

Result:

enter image description here

Enid answered 12/7, 2017 at 18:15 Comment(4)
Thank you, I was looking for someone to explain it in code and you did that. As I said I had a scoreLabel that changes and is written in code, so I would have to apply a shadow to it no matter what number/label change it displays, I also forgot to import UIKit so I'm glad you kept that in the code.Calculate
If your label has a backgroundColor, this will not work. For a text-based solution, see @ingconti's answer.Headwards
@Headwards - That is another good approach - with a couple "gotchas". When using .adjustsFontSizeToFitWidth = true or Dynamic Type fonts - particularly when wrapping to multiple lines - the shadow can get cut off at the bottom (with or without a background color). Personally, if I were to need this, I'd likely embed the label in a UIView for its background.Enid
@Headwards - in addition, when using Dynamic Type, the attributedText font will not be auto-updated.Enid
S
29

UILabel has a property for changing its shadow, the image below shows the property in attributes inspector and the result.

enter image description here

Result of that effect on label enter image description here

Stromboli answered 12/7, 2017 at 16:47 Comment(2)
Thank you for the answer, however I don't seem to have the UILabel settings you have, I've checked all tab-a-longs. Wanted to write it in code anyway so this would not be the solution I was looking for, but I'll use this in the future in storyboard/sks.Calculate
@RasmusRossen, go to ATTRIBUTES and it is the FOURTH section down - it's right there! Look for "Highlighted".Titicaca
C
22

You can write an extension and use it. Place the extension code outside of class ViewController.

I like subtle shadow.
enter image description here

extension UILabel {
    func textDropShadow() {
        self.layer.masksToBounds = false
        self.layer.shadowRadius = 2.0
        self.layer.shadowOpacity = 0.2
        self.layer.shadowOffset = CGSize(width: 1, height: 2)
    }

    static func createCustomLabel() -> UILabel {
        let label = UILabel()
        label.textDropShadow()
        return label
    }
}

On your label simply call this method

myLabel.textDropShadow()
Crowboot answered 15/11, 2017 at 9:31 Comment(1)
If your label has a backgroundColor, this will not work. For a text-based solution, see @ingconti's answer.Headwards
D
7

works fine but add shadow to ALL label, not to text.

in this case:

class ViewController: UIViewController {

    @IBOutlet weak var label: UILabel!
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let shadow = NSShadow()
        shadow.shadowColor = UIColor.blue
        shadow.shadowBlurRadius = 10
        
        let attrs: [NSAttributedString.Key: Any] = [
            .font: UIFont.systemFont(ofSize: 36),
            .foregroundColor: UIColor.red,
            .shadow: shadow
        ]
        
        let s = "MY TEXT"
        let attributedText = NSAttributedString(string: s, attributes: attrs)
        self.label.attributedText = attributedText
    }


}


You will get:

[![enter image description here][1]][1]


  [1]: https://i.sstatic.net/CRMpg.png




**note:** You must add attributed string every time, as shadow is an attribute of string, not label, otherwise you can also derive class and override "setText". (keeping attributes inside the object in a a property you can set on init/setter)
Diggins answered 28/7, 2019 at 10:12 Comment(0)
Q
6

Swift 4, IBInspectable using extension

extension UILabel {

    @IBInspectable var isShadowOnText: Bool {
        get {
            return self.isShadowOnText
        }
        set {
            guard (newValue as? Bool) != nil else {
                return
            }

            if newValue == true{

                self.layer.shadowColor = UIColor.black.cgColor
                self.layer.shadowRadius = 2.0
                self.layer.shadowOpacity = 1.0
                self.layer.shadowOffset = CGSize(width: 2, height: 2)
                self.layer.masksToBounds = false
            }
        }
    }
}
Quantifier answered 20/7, 2018 at 13:18 Comment(0)
C
5

Swift 4 - Extension with shadow parameters:

 // Label Shadow
    extension UILabel {
        func lblShadow(color: UIColor , radius: CGFloat, opacity: Float){
            self.textColor = color
            self.layer.masksToBounds = false
            self.layer.shadowRadius = radius
            self.layer.shadowOpacity = opacity

            self.layer.shadowOffset = CGSize(width: 1, height: 1)
            self.layer.shouldRasterize = true
            self.layer.rasterizationScale = UIScreen.main.scale
        }
    }

On your label simply call this method

let titleColor = UIColor(red:0.08, green:0.08, blue:0.08, alpha:1.0)
titleLbl.lblShadow(color: titleColor, radius: 3, opacity: 0.25)
Crowboot answered 22/4, 2018 at 7:42 Comment(0)
B
1

U can make a extension method for all UIView subclasses.

extension UIView {
    func drawShadow(offset: CGSize, opacity: Float = 0.25, color: UIColor = .black, radius: CGFloat = 1) {
        layer.masksToBounds = false
        layer.shadowColor = color.cgColor
        layer.shadowOffset = offset
        layer.shadowOpacity = opacity
        layer.shadowRadius = radius
    }
}
Biles answered 29/9, 2020 at 6:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.