적당한 고통은 희열이다

- 댄 브라운 '다빈치 코드' 중에서

Swift iOS 앱 개발/실전 Swift

[Swift iOS] UILabel Gradient color (+ SwiftUI gradient text)

hongssup_ 2024. 1. 25. 11:06
반응형

UILabel 에 그라데이션 색상 입히기

GPT 는 소용이 없어연,, ㅎ

알려준대로 해도 그라데이션 전혀 안먹히더라 

 

final class GradientLabel: UILabel {
    private var colors: [UIColor] = [.red, .yellow]
    private var startPoint: CGPoint = CGPoint(x: 0.0, y: 0.5)
    private var endPoint: CGPoint = CGPoint(x: 1.0, y: 0.5)
    private var gradientLayer = CAGradientLayer()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        applyColors()
    }
    
    func update(colors: [UIColor], startPoint: CGPoint, endPoint: CGPoint) {
        self.colors = colors
        self.startPoint = startPoint
        self.endPoint = endPoint
        applyColors()
    }
    
    private func setup() {
        isAccessibilityElement = true
        applyColors()
    }
    
    private func applyColors() {
        let gradient = getGradientLayer(bounds: self.bounds)
        textColor = gradientColor(bounds: self.bounds, gradientLayer: gradient)
    }
    
    private func getGradientLayer(bounds: CGRect) -> CAGradientLayer {
        gradientLayer.frame = bounds
        gradientLayer.colors = colors.map { $0.cgColor }
        gradientLayer.startPoint = startPoint
        gradientLayer.endPoint = endPoint
        return gradientLayer
    }
}
extension UIView {
    func gradientColor(bounds: CGRect, gradientLayer: CAGradientLayer) -> UIColor? {
        UIGraphicsBeginImageContext(gradientLayer.bounds.size)
        guard let context = UIGraphicsGetCurrentContext() else {
            return nil
        }
        gradientLayer.render(in: context)
        guard let image = UIGraphicsGetImageFromCurrentImageContext() else {
            return nil
        }
        UIGraphicsEndImageContext()
        return UIColor(patternImage: image)
    }
}

참고했던 코드에서는 UIGraphicsBeginImageContext 를 사용해서 그라데이션 색상 이미지를 만들어주었는데, 

이거슨 곧 deprecated 될 예정이라고 하더라.. 뭐 어때 평소처럼 가볍게 경고를 무시하고 빌드를 했는데

iOS 17 에서 다음과 같은 에러와 함께 크래시가 나는 이슈가 있더라..! 😱

Thread 1: "UIGraphicsBeginImageContext() failed to allocate CGBitampContext: size={0, 0}, scale=1.000000, bitmapInfo=0x2002. Use UIGraphicsImageRenderer to avoid this assert."

 

UIGraphicsBeginImageContext 대신 UIGraphicsImageRenderer 를 사용하라길래 다음과 같이 수정해주었더니 잘 뜨더라.

func gradientColor(bounds: CGRect, gradientLayer: CAGradientLayer) -> UIColor? {
    let renderer = UIGraphicsImageRenderer(size: gradientLayer.bounds.size)
    let image = renderer.image {context in
        gradientLayer.render(in: context.cgContext)
    }
    return UIColor(patternImage: image)
}

 

 

 

SwiftUI gradient text

스유에서는 text에 그라데이션을 어떻게 적용할까 찾아봤도니

개꿀..!!! 훠어얼씬 간단하고 편하다. 

Text("Gradient")
    .font(.title)
    .foregroundStyle (
        LinearGradient(
        	colors: [.red, .yellow], 
            startPoint: .leading, 
            endPoint: .trailing)
        )
    )

 


참고 : 

- GradientLabel

https://gist.github.com/SergLam/1f49d05fe1dc042e1e9d88537f9413a3

- SwiftUI gradient text 

https://sarunw.com/posts/how-to-render-text-with-color-gradient-in-swiftui/

 

 

728x90
반응형