调整CATextLayer的大小以适合iOS上的文本 [英] Resize CATextLayer to fit text on iOS

查看:206
本文介绍了调整CATextLayer的大小以适合iOS上的文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

到目前为止,我所有的研究似乎都表明不可能准确地做到这一点。我在开始时可用的唯一两个选项是:

All my research so far seems to indicate it is not possible to do this accurately. The only two options available to me at the outset were:


a)使用CATextLayer的布局管理器 - 在iOS上不可用4.0

a) Using a Layout manager for the CATextLayer - not available on iOS as of 4.0

b)使用sizeWithFont:constrainedToSize:lineBreakMode:并根据此处返回的大小调整CATextLayer的帧。

b) Use sizeWithFont:constrainedToSize:lineBreakMode: and adjust the frame of the CATextLayer according to the size returned here.

选项(b)是最简单的方法,应该有效。毕竟,它与UILabels完美配合。但是当我将相同的帧计算应用于CATextLayer时,框架总是比预期或需要的要大一些。

Option (b), being the simplest approach, should work. After all, it works perfectly with UILabels. But when I applied the same frame calculation to CATextLayer, the frame was always turning out to be a bit bigger than expected or needed.

事实证明, CATextLayers和UILabels中的行间距(对于相同的字体和大小)是不同的。因此,sizeWithFont(其行间距计算将与UILabel的行间距计算匹配)不会返回CATextLayers的预期大小。

这进一步证明了通过使用UILabel打印相同的文本,与CATextLayer打印相同的文本并比较结果。第一行中的文本完全重叠(它是相同的字体),但CATextLayer中的行间距比UILabel略短。 (对不起,我现在无法上传截图,因为我已经包含了机密数据,我现在没有时间制作一个示例项目来获取干净的截图。我会稍后上传它们给后人,当时我有时间)

This is further proven by printing the same text using a UILabel, as against a CATextLayer and comparing the results. The text in the first line overlaps perfectly (it being the same font), but the line-spacing in CATextLayer is just a little shorter than in UILabel. (Sorry I can't upload a screenshot right now as the ones I already have contain confidential data, and I presently don't have the time to make a sample project to get clean screenshots. I'll upload them later for posterity, when I have the time)

这是一个奇怪的区别,但我认为可以通过为我使用的NSAttributedString指定适当的属性来调整CATextLayer中的间距那里,但似乎并非如此。查看CFStringAttributes.h我找不到可能与行间距相关的单个属性。

This is a weird difference, but I thought it would be possible to adjust the spacing in the CATextLayer by specifying the appropriate attribute for the NSAttributedString I use there, but that does not seem to be the case. Looking into CFStringAttributes.h I can't find a single attribute that could be related to line-spacing.

Bottomline:

因此,在需要适合其文本的图层的情况下,似乎无法在iOS上使用CATextLayer。我是对的,还是我错过了什么?

So it seems like it's not possible to use CATextLayer on iOS in a scenario where the layer is required to fit to its text. Am I right on this or am I missing something?

PS:


  1. 我想使用CATextLayer和NSAttributedString的原因是因为要显示的字符串在不同点上的颜色不同。我想我必须一如既往地回去手工绘制琴弦....当然总是可以选择从sizeWithFont中删除结果以获得正确的行高。

  1. The reason I wanted to use CATextLayer and NSAttributedString's is because the string to be displayed is to be colored differently at different points. I guess I'd just have to go back to drawing the strings by hand as always....of course there's always the option of hacking the results from sizeWithFont to get the proper line-height.

稍微滥用代码标签以使帖子更具可读性。

Abusing the 'code' tags a little to make the post more readable.

我无法标记带有'CATextLayer'的帖子 - 令人惊讶的是目前还没有这样的标签。如果有足够声誉的人碰到这篇文章,请相应地标记。

I'm not able to tag the post with 'CATextLayer' - surprisingly no such tags exist at the moment. If someone with enough reputation bumps into this post, please tag it accordingly.


推荐答案

试试这个:

- (CGFloat)boundingHeightForWidth:(CGFloat)inWidth withAttributedString:(NSAttributedString *)attributedString {
    CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString( (CFMutableAttributedStringRef) attributedString); 
    CGSize suggestedSize = CTFramesetterSuggestFrameSizeWithConstraints(framesetter, CFRangeMake(0, 0), NULL, CGSizeMake(inWidth, CGFLOAT_MAX), NULL);
    CFRelease(framesetter);
    return suggestedSize.height;
}

您必须将NSString转换为NSAttributedString。如果 CATextLayer ,您可以使用以下 CATextLayer 子类方法:

You'll have to convert your NSString to NSAttributedString. In-case of CATextLayer, you can use following CATextLayer subclass method:

- (NSAttributedString *)attributedString {

    // If string is an attributed string
    if ([self.string isKindOfClass:[NSAttributedString class]]) {
        return self.string;
    }

    // Collect required parameters, and construct an attributed string
    NSString *string = self.string;
    CGColorRef color = self.foregroundColor;
    CTFontRef theFont = self.font;
    CTTextAlignment alignment;

    if ([self.alignmentMode isEqualToString:kCAAlignmentLeft]) {
        alignment = kCTLeftTextAlignment;

    } else if ([self.alignmentMode isEqualToString:kCAAlignmentRight]) {
        alignment = kCTRightTextAlignment;

    } else if ([self.alignmentMode isEqualToString:kCAAlignmentCenter]) {
        alignment = kCTCenterTextAlignment;

    } else if ([self.alignmentMode isEqualToString:kCAAlignmentJustified]) {
        alignment = kCTJustifiedTextAlignment;

    } else if ([self.alignmentMode isEqualToString:kCAAlignmentNatural]) {
        alignment = kCTNaturalTextAlignment;
    }

    // Process the information to get an attributed string
    CFMutableAttributedStringRef attrString = CFAttributedStringCreateMutable(kCFAllocatorDefault, 0);

    if (string != nil)
        CFAttributedStringReplaceString (attrString, CFRangeMake(0, 0), (CFStringRef)string);

    CFAttributedStringSetAttribute(attrString, CFRangeMake(0, CFAttributedStringGetLength(attrString)), kCTForegroundColorAttributeName, color);
    CFAttributedStringSetAttribute(attrString, CFRangeMake(0, CFAttributedStringGetLength(attrString)), kCTFontAttributeName, theFont);

    CTParagraphStyleSetting settings[] = {kCTParagraphStyleSpecifierAlignment, sizeof(alignment), &alignment};
    CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings, sizeof(settings) / sizeof(settings[0]));
    CFAttributedStringSetAttribute(attrString, CFRangeMake(0, CFAttributedStringGetLength(attrString)), kCTParagraphStyleAttributeName, paragraphStyle);    
    CFRelease(paragraphStyle);

    NSMutableAttributedString *ret = (NSMutableAttributedString *)attrString;

    return [ret autorelease];
}

HTH。

这篇关于调整CATextLayer的大小以适合iOS上的文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆