LoginSignup
15
8

More than 5 years have passed since last update.

UILabelの文字色をグラデーションさせる

Last updated at Posted at 2017-09-01

やりたいこと

UILabelで文字を横にグラデーションさせたい。(文字毎にグラデーションさせる場合は背景設定すれば良いだけになる。後述)

Screen Shot 2017-08-29 at 12.19.47.png

グラデのかかったUIViewを作成し、UILabelをUIImageViewに変換して、マスク処理をかけてやるとこれが作成できる。

コード

    func ここから() -> UIImageView {
        let label: UILabel = makeLabel(text: "ABCDEFG")
        let imageReference: CGImage = makeGradientCGImage(frame: label.bounds)
        let maskReference: CGImage = convertImage(label).cgImage!
        return makeMaskedImage(imageReference: imageReference, maskReference: maskReference)
    }

    private func convertImage(_ view: UIView) -> UIImage {
        UIGraphicsBeginImageContextWithOptions(view.frame.size, false, UIScreen.main.scale)
        let context:CGContext = UIGraphicsGetCurrentContext()!
        context.translateBy(x: -view.frame.origin.x, y: -view.frame.origin.y)
        view.layer.render(in: context)
        let renderedImage:UIImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return renderedImage
    }

    private func makeLabel(text: String) -> UILabel {
        let label = UILabel()
        label.font = UIFont.systemFont(20)
        label.textColor = UIColor.black
        label.backgroundColor = UIColor.white
        label.text = text
        label.sizeToFit()
        return label
    }

    private func makeGradientCGImage(frame: CGRect) -> CGImage {
        let gradientView = UIView(frame: frame)
        let layer: CAGradientLayer = CAGradientLayer()
        layer.frame = gradientView.bounds
        layer.startPoint = CGPoint(x: 0, y: 0.5)
        layer.endPoint = CGPoint(x: 1.0, y: 0.5)
        layer.colors = [UIColor.colorWithHex(0xFFD195).cgColor, UIColor.colorWithHex(0xF5670C).cgColor]
        gradientView.layer.addSublayer(layer)
        return gradientView.convertImage(false).cgImage!
    }

    private func makeMaskedImage(imageReference: CGImage, maskReference: CGImage) -> UIImageView {

        let imageMask = CGImage(maskWidth: maskReference.width,
                                height: maskReference.height,
                                bitsPerComponent: maskReference.bitsPerComponent,
                                bitsPerPixel: maskReference.bitsPerPixel,
                                bytesPerRow: maskReference.bytesPerRow,
                                provider: maskReference.dataProvider!,
                                decode: nil,
                                shouldInterpolate: true)!

        let maskedReference: CGImage = imageReference.masking(imageMask)!
        return UIImageView(image: UIImage(cgImage: maskedReference))
    }

補足

文字毎にグラデーションさせたい場合は、1pxの画像を用意するのがシンプルで良い解決方法のようである。
https://stackoverflow.com/a/4558480

15
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
8