You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift实现带交叉背景色的45度倾斜UILabel

嘿,刚好我之前做过类似的效果,给你分享两种实用的实现方案,都能完美达到你想要的45度倾斜+交叉背景的UILabel效果~

方案一:自定义UILabel子类(封装性强,复用方便)

这种方式把背景绘制和文字倾斜逻辑封装在子类里,后续使用直接实例化即可。

import UIKit

class DiagonalCrossLabel: UILabel {
    // 可配置的交叉背景色
    var crossBgColor: UIColor = .systemOrange {
        didSet { setNeedsDisplay() }
    }
    // 交叉线条的粗细
    var crossLineWidth: CGFloat = 5.0 {
        didSet { setNeedsDisplay() }
    }
    
    override func draw(_ rect: CGRect) {
        super.draw(rect)
        let context = UIGraphicsGetCurrentContext()!
        
        // 1. 绘制交叉背景
        context.saveGState()
        crossBgColor.setFill()
        
        // 左上到右下的斜向色块
        let topLeftPath = UIBezierPath()
        topLeftPath.move(to: CGPoint(x: rect.minX, y: rect.minY))
        topLeftPath.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
        topLeftPath.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - crossLineWidth))
        topLeftPath.addLine(to: CGPoint(x: rect.minX, y: rect.minY + crossLineWidth))
        topLeftPath.close()
        topLeftPath.fill()
        
        // 右上到左下的斜向色块
        let topRightPath = UIBezierPath()
        topRightPath.move(to: CGPoint(x: rect.maxX, y: rect.minY))
        topRightPath.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
        topRightPath.addLine(to: CGPoint(x: rect.minX, y: rect.maxY - crossLineWidth))
        topRightPath.addLine(to: CGPoint(x: rect.maxX, y: rect.minY + crossLineWidth))
        topRightPath.close()
        topRightPath.fill()
        context.restoreGState()
        
        // 2. 绘制45度倾斜的文字
        context.saveGState()
        let rotationAngle = CGFloat.pi / 4 // 45度对应的弧度
        context.translateBy(x: rect.midX, y: rect.midY)
        context.rotate(by: rotationAngle)
        context.translateBy(x: -rect.midX, y: -rect.midY)
        
        super.drawText(in: rect)
        context.restoreGState()
    }
    
    // 修正文字排版区域,避免旋转后被截断
    override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
        let rotatedBounds = bounds.applying(CGAffineTransform(rotationAngle: CGFloat.pi / 4))
        let textRect = super.textRect(forBounds: rotatedBounds, limitedToNumberOfLines: numberOfLines)
        return textRect.applying(CGAffineTransform(rotationAngle: -CGFloat.pi / 4))
    }
    
    override func drawText(in rect: CGRect) {
        let rotatedRect = rect.applying(CGAffineTransform(rotationAngle: CGFloat.pi / 4))
        super.drawText(in: rotatedRect)
    }
}

使用方式

在ViewController里直接实例化配置即可:

let myLabel = DiagonalCrossLabel(frame: CGRect(x: 80, y: 200, width: 220, height: 70))
myLabel.text = "Swift iOS"
myLabel.font = .boldSystemFont(ofSize: 24)
myLabel.textColor = .white
myLabel.crossBgColor = .systemOrange
myLabel.crossLineWidth = 6.0
view.addSubview(myLabel)
方案二:CALayer组合实现(更灵活,适合复杂背景)

如果你的交叉背景需要更复杂的样式(比如斜线纹理、虚线效果),用Layer组合的方式会更灵活。

import UIKit

class LayerBasedCrossLabel: UILabel {
    private let crossBgLayer = CAShapeLayer()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        setupBgLayer()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        setupBgLayer()
    }
    
    private func setupBgLayer() {
        crossBgLayer.fillColor = UIColor.systemOrange.cgColor
        layer.insertSublayer(crossBgLayer, at: 0)
        
        // 给Label添加45度旋转
        transform = CGAffineTransform(rotationAngle: CGFloat.pi / 4)
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        updateCrossBgPath()
    }
    
    private func updateCrossBgPath() {
        let rect = bounds
        let path = UIBezierPath()
        
        // 绘制交叉色块(和方案一逻辑一致,可自定义修改)
        path.move(to: CGPoint(x: rect.minX, y: rect.minY))
        path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
        path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - 5))
        path.addLine(to: CGPoint(x: rect.minX, y: rect.minY + 5))
        path.close()
        
        path.move(to: CGPoint(x: rect.maxX, y: rect.minY))
        path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY))
        path.addLine(to: CGPoint(x: rect.minX, y: rect.maxY - 5))
        path.addLine(to: CGPoint(x: rect.maxX, y: rect.minY + 5))
        path.close()
        
        crossBgLayer.path = path.cgPath
    }
}
一些实用小贴士
  • 如果需要反向倾斜(-45度),只需把旋转角度改成-CGFloat.pi / 4即可。
  • 可以修改crossLineWidth或者路径逻辑,调整交叉背景的密度、样式,比如换成密集的斜线填充。
  • 若需要修正旋转后的点击区域,可重写point(inside:with:)方法,将点击点转换为旋转后的坐标进行判断。

内容的提问来源于stack exchange,提问作者Parth Dhorda

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 07:07:15