Is it possible to add a UILabel
to a CALayer
without subclassing and drawing it in drawInContext:
?
Thanks!
Is it possible to add a UILabel
to a CALayer
without subclassing and drawing it in drawInContext:
?
Thanks!
I don't think you can add a UIView subclass to a CALayer object. However if you want to draw text on a CALayer object, it can be done using the drawing functions provided in NSString UIKit additions as shown below. While my code is done in the delegate's drawLayer:inContext method, the same can be used in subclass' drawInContext: method. Is there any specific UILabel functionality that you want to leverage?
- (void) drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
CGContextSetFillColorWithColor(ctx, [[UIColor darkTextColor] CGColor]);
UIGraphicsPushContext(ctx);
/*[word drawInRect:layer.bounds
withFont:[UIFont systemFontOfSize:32]
lineBreakMode:UILineBreakModeWordWrap
alignment:UITextAlignmentCenter];*/
[word drawAtPoint:CGPointMake(30.0f, 30.0f)
forWidth:200.0f
withFont:[UIFont boldSystemFontOfSize:32]
lineBreakMode:UILineBreakModeClip];
UIGraphicsPopContext();
}
CATextLayer *label = [[CATextLayer alloc] init];
[label setFont:@"Helvetica-Bold"];
[label setFontSize:20];
[label setFrame:validFrame];
[label setString:@"Hello"];
[label setAlignmentMode:kCAAlignmentCenter];
[label setForegroundColor:[[UIColor whiteColor] CGColor]];
[layer addSublayer:label];
[label release];
I don't think you can add a UIView subclass to a CALayer object. However if you want to draw text on a CALayer object, it can be done using the drawing functions provided in NSString UIKit additions as shown below. While my code is done in the delegate's drawLayer:inContext method, the same can be used in subclass' drawInContext: method. Is there any specific UILabel functionality that you want to leverage?
- (void) drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx {
CGContextSetFillColorWithColor(ctx, [[UIColor darkTextColor] CGColor]);
UIGraphicsPushContext(ctx);
/*[word drawInRect:layer.bounds
withFont:[UIFont systemFontOfSize:32]
lineBreakMode:UILineBreakModeWordWrap
alignment:UITextAlignmentCenter];*/
[word drawAtPoint:CGPointMake(30.0f, 30.0f)
forWidth:200.0f
withFont:[UIFont boldSystemFontOfSize:32]
lineBreakMode:UILineBreakModeClip];
UIGraphicsPopContext();
}
Just to document my approach, I did it like this in Swift 4+ :
let textlayer = CATextLayer()
textlayer.frame = CGRect(x: 20, y: 20, width: 200, height: 18)
textlayer.fontSize = 12
textlayer.alignmentMode = .center
textlayer.string = stringValue
textlayer.isWrapped = true
textlayer.truncationMode = .end
textlayer.backgroundColor = UIColor.white.cgColor
textlayer.foregroundColor = UIColor.black.cgColor
caLayer.addSublayer(textlayer) // caLayer is and instance of parent CALayer
Your UILabel already has a CALayer behind it. If you are putting together several CALayers, you can just add the UILabel's layer as a sublayer of one of those (by using its layer
property).
If it's direct text drawing in a layer that you want, the UIKit NSString additions that Deepak points to are the way to go. For an example of this in action, the Core Plot framework has a Mac / iPhone platform-independent CALayer subclass which does text rendering, CPTextLayer.
Add a CATextLayer as a sublayer and set the string property. That would be easiest and you can easily use a layout manager to make it very generic.
The answers below are fine, just make sure you add otherwise you text will be blurry:
textLayer.contentsScale = UIScreen.main.scale
Final code for Swift:
let textLayer = CATextLayer()
textLayer.frame = CGRect(x: 0, y: 0, width: 60, height: 15)
textLayer.fontSize = 12
textLayer.string = "my text"
textLayer.foregroundColor = UIColor.red.cgColor
textLayer.contentsScale = UIScreen.main.scale
class MyCALayer: CALayer {
......
override func draw(in ctx: CGContext) {
UIGraphicsPushContext(ctx)
let text = "這是一段普通的文字"
let textAttrs: [NSAttributedString.Key: Any] = [.font: UIFont.systemFont(ofSize: 20), .foregroundColor: UIColor.blue]
var drawPoint = CGPoint(x: 0, y: 0)
for char in text {
let word = NSAttributedString(string: String(char),
attributes: textAttrs)
let wordBounds = word.boundingRect(with: CGSize(width: .max, height: .max), context: nil)
word.draw(at: drawPoint)
drawPoint = CGPoint(x: drawPoint.x + wordBounds.width, y: drawPoint.y)
let whitespace = NSAttributedString(string: " ", attributes: textAttrs)
let whitespaceBounds = whitespace.boundingRect(with: CGSize(width: .max, height: .max), context: nil)
whitespace.draw(at: drawPoint)
drawPoint = CGPoint(x: drawPoint.x + whitespaceBounds.width, y: drawPoint.y)
}
UIGraphicsPopContext()
}
......
}
The result
Always remember to remove previous sublayers, if you gonna add another one, to prevent duplicating views:
if let sublayers = layer.sublayers {
for sublayer in sublayers {
sublayer.removeFromSuperlayer()
}
}
© 2022 - 2024 — McMap. All rights reserved.