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
相关产品推荐
相关产品推荐

