Computer >> Hướng Dẫn Máy Tính >  >> Lập Trình >> iOS

Cách thêm bóng (shadow) cho text UILabel trong iOS Swift

Thêm shadow cho text làm UI đẹp, nổi bật, tăng trải nghiệm người dùng (game, app trẻ em, heading...).

Cách: Extension UILabel

Bước 1: Tạo dự án

Xcode → Single View App → Tên: "ShadowText".

Bước 2: Storyboard

Thêm UILabel → Tạo @IBOutlet weak var lblHelloWorld: UILabel!

Bước 3: Extension UILabel


extension UILabel {
    func addTextShadow(color: UIColor = .black,
                       offset: CGSize = CGSize(width: 1, height: 1),
                       radius: CGFloat = 3.0,
                       opacity: Float = 1.0) {
        
        self.textColor = color
        self.layer.masksToBounds = false        // Quan trọng: cho shadow ra ngoài bounds
        self.layer.shadowColor = color.cgColor
        self.layer.shadowOffset = offset
        self.layer.shadowRadius = radius
        self.layer.shadowOpacity = opacity
        self.layer.shouldRasterize = true       // Tối ưu performance
        self.layer.rasterizationScale = UIScreen.main.scale
    }
}

Bước 4: Gọi trong viewDidLoad


override func viewDidLoad() {
    super.viewDidLoad()
    
    // Đỏ, shadow đen offset (1,1), radius 6, opacity 1
    lblHelloWorld.addTextShadow(color: .systemRed, 
                                offset: CGSize(width: 2, height: 2), 
                                radius: 6, 
                                opacity: 0.8)
}

Cách thêm bóng (shadow) cho text UILabel trong iOS Swift

Các biến thể Shadow phổ biến

1. Shadow mờ nhẹ (Subtle)


label.addTextShadow(color: .black, offset: CGSize(width: 0, height: 1), radius: 1, opacity: 0.3)

2. Shadow nổi (Neumorphism/Float effect)


label.addTextShadow(color: .white, offset: CGSize(width: -2, height: -2), radius: 4, opacity: 0.5)
label.addTextShadow(color: .black, offset: CGSize(width: 2, height: 2), radius: 4, opacity: 0.3)
// Cần 2 label chồng nhau hoặc dùng attributedString với NSShadow

3. Shadow nhiều màu (Gradient shadow - phức tạp)

Cần dùng CAGradientLayer làm mask cho shadow layer.

Cách 2: NSAttributedString (Cho phần text trong label)


let attributedString = NSMutableAttributedString(string: "Hello World")

let shadow = NSShadow()
shadow.shadowColor = UIColor.black.withAlphaComponent(0.5)
shadow.shadowOffset = CGSize(width: 2, height: 2)
shadow.shadowBlurRadius = 4

attributedString.addAttribute(.shadow, value: shadow, range: NSRange(location: 0, length: 5)) // Chỉ "Hello"

label.attributedText = attributedString

Lưu ý quan trọng

  • masksToBounds = false (mặc định true) - BẮT BUỘC để shadow hiển thị ra ngoài bounds
  • shouldRasterize = true + rasterizationScale - Tối ưu GPU, tránh re-render liên tục khi scroll
  • Shadow color nên dùng UIColor.black.withAlphaComponent(0.3-0.5) tự nhiên hơn black solid
  • Performance: Quá nhiều label có shadow + scroll → lag. Cân nhắc rasterize hoặc pre-render
  • Dark Mode: Shadow color có thể cần dynamic (light mode: đen, dark mode: trắng/clear)

Dynamic Shadow cho Dark Mode


extension UILabel {
    func addDynamicTextShadow(radius: CGFloat = 3, opacity: Float = 0.3, offset: CGSize = .init(width: 1, height: 1)) {
        self.layer.masksToBounds = false
        self.layer.shadowRadius = radius
        self.layer.shadowOpacity = opacity
        self.layer.shadowOffset = offset
        self.layer.shouldRasterize = true
        self.layer.rasterizationScale = UIScreen.main.scale
        
        // Dynamic shadow color
        self.layer.shadowColor = UIColor { traitCollection in
            traitCollection.userInterfaceStyle == .dark 
                ? UIColor.white.withAlphaComponent(0.3).cgColor 
                : UIColor.black.withAlphaComponent(0.3).cgColor
        }.cgColor
    }
}