How to mask with UILabel

Issue #603

Need to set correct frame for mask layer or UILabel, as it is relative to the coordinate of the view to be masked

1
2
3
4
5
6
7
8
9
let aView = UIView(frame: .init(x: 100, y: 110, width: 200, height: 100))

let textLayer = CATextLayer()
textLayer.foregroundColor = UIColor.white.cgColor
textLayer.string = "Hello world"
textLayer.font = UIFont.preferredFont(forTextStyle: .largeTitle)
textLayer.frame = aView.bounds

aView.layer.mask = textLayer

Use sizeToFit to ensure frame for UILabel

1
2
3
4
5
6
7
8
9
let label = UILabel()
label.frame.origin = CGPoint(x: 80, y: 80)

label.textColor = UIColor.black
label.font = UIFont.preferredFont(forTextStyle: .largeTitle)
label.text = "ABC"
label.sizeToFit()

aView.mask = label

Change bounds.origin

1
2
label.frame.origin = CGPoint(x: 50, y: 50)
aView.bounds.origin = label.frame.origin

Adding label to view hierarchy seems to remove masking effect. Need to set mask later

1
2
3
view.addSubview(aView)
view.addSubview(label)
aView.mask = label

Can’t add overlayView to UILabel and use UILabel as mask, cause cycler CALayer

After using UILabel as mask, its superview is nil

1
2
aView.mask = label
label.superview == nil

Mask with snapshot from UILabel. Need to set correct frame for aView and maskLayer

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
let maskLayer = CALayer()
maskLayer.contents = label.makeScreenshot().cgImage
maskLayer.contentsGravity = .resizeAspect

aView.frame = label.bounds
maskLayer.frame = aView.bounds
aView.layer.mask = maskLayer
label.addSubview(aView)

extension UIView {
func makeScreenshot() -> UIImage {
let renderer = UIGraphicsImageRenderer(bounds: self.bounds)
return renderer.image { (context) in
self.layer.render(in: context.cgContext)
}
}
}

Comments