问题描述
|
到目前为止,我所有的研究似乎都表明不可能准确地做到这一点。一开始对我来说只有两个选择:
a)为CATextLayer使用布局管理器-从4.0版本开始在iOS上不可用
b)使用sizeWithFont:constrainedToSize:lineBreakMode:并根据此处返回的大小调整CATextLayer的框架。
选项(b)是最简单的方法,应该起作用。毕竟,它与UILabels完美配合。但是,当我将相同的帧计算应用于CATextLayer时,该帧总是比预期或需要的要大一些。
事实证明,CATextLayers和UILabels中的行距(对于相同的字体和大小)是不同的。结果,sizeWithFont(其行距计算将与UILabels的行距计算匹配)不会返回CATextLayers的预期大小。
通过使用UILabel打印相同的文本(相对于CATextLayer)并比较结果,可以进一步证明这一点。第一行中的文本完全重叠(它是相同的字体),但是CATextLayer中的行距仅比UILabel中的短。 (对不起,我现在无法上传屏幕截图,因为我已经包含了机密数据,并且我目前没有时间制作示例项目来获取清晰的屏幕截图。我稍后将其上传以用于有时间的话,后代)
这是一个怪异的区别,但是我认为可以通过为我在此处使用的NSAttributedString指定适当的属性来调整CATextLayer中的间距,但这似乎并非如此。调查CFStringAttributes.h我找不到与行间距有关的单个属性。
底线:
因此,在要求图层适合其文本的情况下,似乎无法在iOS上使用CATextLayer。我是对的还是错过了什么?
附言:
我之所以要使用CATextLayer和NSAttributedString \,是因为要显示的字符串在不同点的颜色不同。我想我只需要像往常一样手动绘制字符串即可。...当然,总有一种选择,可以从sizeWithFont修改结果以获取正确的行高。
稍微滥用\'code \'标记可使帖子更具可读性。
我无法使用\'CATextLayer \'标记帖子-令人惊讶的是,目前尚无此类标记。如果有足够声誉的人进入此职位,请相应地对其进行标记。
解决方法
尝试这个:
- (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
,可以使用以下ѭ1following子类方法:
- (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,(CFStringRef)string);
CFAttributedStringSetAttribute(attrString,CFAttributedStringGetLength(attrString)),kCTForegroundColorAttributeName,color);
CFAttributedStringSetAttribute(attrString,kCTFontAttributeName,theFont);
CTParagraphStyleSetting settings[] = {kCTParagraphStyleSpecifierAlignment,sizeof(alignment),&alignment};
CTParagraphStyleRef paragraphStyle = CTParagraphStyleCreate(settings,sizeof(settings) / sizeof(settings[0]));
CFAttributedStringSetAttribute(attrString,kCTParagraphStyleAttributeName,paragraphStyle);
CFRelease(paragraphStyle);
NSMutableAttributedString *ret = (NSMutableAttributedString *)attrString;
return [ret autorelease];
}
HTH。
, 我有一个简单得多的解决方案,它可能对您不起作用。
如果您没有对CATextLayer做任何无法执行UILabel的特殊操作,请制作一个CALayer并将UILabel的图层添加到CALayer
UILabel*label = [[UILabel alloc]init];
//Do Stuff to label
CALayer *layer = [CALayer layer];
//Set Size/Position
[layer addSublayer:label.layer];
//Do more stuff to layer
, 使用LabelKit,您不再需要CATextLayer
。不再有错误的行距和更宽的字符,所有这些都以与UILabel相同的方式绘制,同时仍具有动画效果。
, 该页面使我足够创建一个水平居中的简单CATextLayer:http://lists.apple.com/archives/quartz-dev/2008/Aug/msg00016.html
- (void)drawInContext:(CGContextRef)ctx {
CGFloat height,fontSize;
height = self.bounds.size.height;
fontSize = self.fontSize;
CGContextSaveGState(ctx);
CGContextTranslateCTM(ctx,0.0,(fontSize-height)/2.0 * -1.0);
[super drawInContext:ctx];
CGContextRestoreGState(ctx);
}