UIKit实现一个渐变文字的UILabel(核心思想及实现过程)

一. 引言

在日常开发中渐变背景我们并不陌生,而且官方几乎也给了方案使用CAGradientLayer特殊图层。但是渐变文字呢?这个设计样式不太常见,但是如果是做社交类应用的话,为了凸显用户的身份,会员,贵族等等信息,经常会出现渐变文字甚至是闪烁文字。

提到渐变文字很多人第一反应:

  • 能不能直接给 UILabel 设置渐变色?
  • drawText(in:) 自己画?
  • 或者用图片?

这些方案要么性能一般、要么不够优雅,也不利于组件化复用。

这篇文章我们来实现一个 真正工程可用的渐变文字 UILabel,方案稳定、性能友好,并且可以和常见的渐变按钮、渐变视图保持一致的设计风格。

二. 渐变文字的核心思路

先说结论:

文字本身并不负责显示颜色,颜色来自渐变 Layer;文字只是一个「遮罩(mask)」

整体结构就是:

ZMGradientLabel

└─ CAGradientLayer (真正有颜色)

└─ mask = CATextLayer(文字轮廓)

也就是说:

  • 渐变效果由 CAGradientLayer 提供
  • CATextLayer 只负责定义「文字长什么样」
  • 通过 mask,只显示文字形状区域内的渐变

这是一个 GPU 渲染方案,性能和系统动画完全同级。

三. 渐变文字的具体实现

3.1 定义 ZMGradientLabel

Swift 复制代码
import UIKit

public class ZMGradientLabel: UILabel {

    private let gradientLayer = CAGradientLayer()
    private let textMaskLayer = CATextLayer()

    // MARK: - Init
    public override init(frame: CGRect) {
        super.init(frame: frame)
        commonInit()
    }

    public required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }

    private func commonInit() {
        // UILabel 本身不显示颜色
        textColor = .clear

        // 添加渐变 Layer
        layer.addSublayer(gradientLayer)
        gradientLayer.mask = textMaskLayer

        // CATextLayer 基础配置
        textMaskLayer.contentsScale = UIScreen.main.scale
        textMaskLayer.alignmentMode = .center
        textMaskLayer.truncationMode = .end
    }

    // MARK: - Layout
    public override func layoutSubviews() {
        super.layoutSubviews()
        gradientLayer.frame = bounds
        updateTextMask()
    }

    // MARK: - Text 更新
    private func updateTextMask() {
        textMaskLayer.frame = bounds
        textMaskLayer.string = text
        textMaskLayer.font = font
        textMaskLayer.fontSize = font.pointSize
    }

    public override var text: String? {
        didSet { updateTextMask() }
    }

    public override var font: UIFont! {
        didSet { updateTextMask() }
    }
}

到这里,我们已经完成了:

  • 渐变 Layer 的承载
  • 文字作为 Mask 的映射
  • Auto Layout 下的自适应更新

3.2 配置渐变颜色及方向

我们可以为 ZMGradientLabel 添加一个设置颜色及方向方法,来更新它的渐变颜色:

Swift 复制代码
extension ZMGradientLabel {

    public func setupGradient(
        colors: [UIColor],
        locations: [NSNumber]? = nil,
        direction: ZMGradientDirection = .leftToRight
    ) {
        var cgColors = colors.map { $0.cgColor }
        if cgColors.count == 1 {
            cgColors.append(cgColors[0])
        }

        gradientLayer.colors = cgColors
        gradientLayer.locations = locations

        switch direction {
        case .leftToRight:
            gradientLayer.startPoint = CGPoint(x: 0, y: 0.5)
            gradientLayer.endPoint = CGPoint(x: 1, y: 0.5)
        case .rightToLeft:
            gradientLayer.startPoint = CGPoint(x: 1, y: 0.5)
            gradientLayer.endPoint = CGPoint(x: 0, y: 0.5)
        case .topToBottom:
            gradientLayer.startPoint = CGPoint(x: 0.5, y: 0)
            gradientLayer.endPoint = CGPoint(x: 0.5, y: 1)
        case .bottomToTop:
            gradientLayer.startPoint = CGPoint(x: 0.5, y: 1)
            gradientLayer.endPoint = CGPoint(x: 0.5, y: 0)
        case .topLeftToBottomRight:
            gradientLayer.startPoint = CGPoint(x: 0, y: 0)
            gradientLayer.endPoint = CGPoint(x: 1, y: 1)
        case .bottomLeftToTopRight:
            gradientLayer.startPoint = CGPoint(x: 0, y: 1)
            gradientLayer.endPoint = CGPoint(x: 1, y: 0)
        }
    }
}

其中ZMGradientDirection 是我们自定义的枚举。

3.3 使用渐变文字

在使用时,就和普通的UILabel一样设置内容,设置字体,只是在需要渐变时,调用setupGradient方法来设置它的渐变颜色和方向。

Swift 复制代码
let label = ZMGradientLabel()
label.text = "渐变文字"
label.font = .boldSystemFont(ofSize: 20)

label.setupGradient(
    colors: [.systemPink, .systemOrange],
    direction: .leftToRight
)

支持特性:

  • Auto Layout / SnapKit
  • 动态修改 text / font
  • GPU 渲染,性能稳定

四. 结语

渐变文字看起来是一个「视觉需求」,但背后其实是一个非常典型的 Layer + Mask 应用场景。

相比 drawText 或图片方案,CAGradientLayer + CATextLayer

  • 性能更好(GPU 渲染)
  • 更易复用、易扩展
  • 更符合 UIKit 的底层设计哲学

当你已经有了渐变按钮、渐变背景时,把渐变文字也纳入同一套组件体系,会让整个 UI 在一致性和可维护性上都提升一个层级。

相关推荐
alphardex2 小时前
一个普通魔法师的 2025 年度总结
前端·年终总结
德莱厄斯2 小时前
AI 纪元 3 年,2025 论前端程序员自救
前端·ai编程·vibecoding
WX-bisheyuange2 小时前
基于Spring Boot的社团管理系统的设计与实现
前端·javascript·vue.js·毕业设计
橙某人2 小时前
LogicFlow 插件魔改实录:手把手教你重写动态分组(DynamicGroup)🛠️
前端·javascript·vue.js
阿蔹3 小时前
UI测试自动化-Web-Python-Selenium-2-元素操作、浏览器操作
前端·python·selenium·ui·自动化
谎言西西里3 小时前
React hooks 之 一篇文章掌握 useState 和 useEffect 的核心机制
前端·react.js
Apifox.3 小时前
Apifox 12 月更新| AI 生成用例同步生成测试数据、接口文档完整性检测、设计 SSE 流式接口、从 Git 仓库导入数据
前端·人工智能·git·ai·postman·团队开发
bjzhang753 小时前
使用 HTML + JavaScript 实现滑动验证码
前端·javascript·html
行走的陀螺仪3 小时前
使用uniapp,实现根据时间倒计时执行进度条变化
前端·javascript·uni-app·vue2·h5