Bad_Developer
Bad_Developer

Reputation: 537

Vertical alignment between CALayer and CATextLayer


I'm currently working with CALayer and CATextLayer and I got a stuck when align them in vertical.
I'm create a CALayer for display an image inside it, then add a CATextLayer below CALayer after calculate the text size of CATexLayer, you can see my code for more details:

+ (instancetype)itemWithImage:(UIImage *)image andTitle:(NSString *)title {
    CGSize size = CGSizeMake(MIN(image.size.width, [XFATLayoutAttributes itemWidth]), MIN(image.size.height, [XFATLayoutAttributes itemWidth]));
    CALayer *layer = [CALayer layer];
    layer.contents = (__bridge id)image.CGImage;
    layer.bounds = CGRectMake(0, 0, MIN(size.width, [XFATLayoutAttributes itemImageWidth]), MIN(size.height, [XFATLayoutAttributes itemImageWidth]));

    CATextLayer *label = [[CATextLayer alloc] init];
    [label setFont:@"Helvetica"];
    [label setFontSize:14];
    label.alignmentMode = kCAAlignmentCenter;

    label.backgroundColor = [UIColor redColor].CGColor;
    label.string = title;
    label.foregroundColor = [UIColor colorWithRed:138/255.0 green:138/255.0 blue:143/255.0 alpha:1.0].CGColor;
    label.wrapped = YES;
    label.contentsScale = [UIScreen mainScreen].scale;

    CGSize stringSize = [title sizeWithAttributes:@{NSFontAttributeName: [UIFont fontWithName:@"Helvetica" size:14.0]}];
    label.frame = CGRectMake(-5, layer.bounds.size.height + 5, stringSize.width, stringSize.height + 1);

    [layer addSublayer:label];

    return [[self alloc] initWithLayer:layer];
}

But the problem is the text size are not the same and my CATextLayer was misalignment a little bit like this image: enter image description here

How can I align them in X axis? Please help.
Thanks in advance.

Upvotes: 0

Views: 1002

Answers (1)

schmidt9
schmidt9

Reputation: 4528

You can calculate right X offset this way:

label.frame = CGRectMake((size.width - stringSize.width) / 2, layer.bounds.size.height + 5,
                         stringSize.width, stringSize.height + 1);

Or you can simply make your label width equal to image width since you align text to center:

label.frame = CGRectMake(0, layer.bounds.size.height + 5,
                             size.width, stringSize.height + 1);

BTW I could not make work your method with return [[self alloc] initWithLayer:layer], so I had to return constructed subclass instance itself:

AlignLayer *layer = [AlignLayer layer]; // my subclass
// ...
return layer;

And Apple warns against using initWithLayer: in such situations:

This initializer is used to create shadow copies of layers, for example, for the presentationLayer method. Using this method in any other situation will produce undefined behavior. For example, do not use this method to initialize a new layer with an existing layer’s content.

Upvotes: 1

Related Questions