
一. 引言
在日常开发中渐变背景我们并不陌生,而且官方几乎也给了方案使用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 在一致性和可维护性上都提升一个层级。