2011-06-01 86 views
20

文本符合我所有的研究,到目前爲止,似乎表明它是不可能準確地做到這一點。提供給我的只有兩個選擇從一開始就爲:調整大小CATextLayer在iOS

a)使用的CATextLayer佈局管理器 - 不適用於iOS爲4.0

b)利用sizeWithFont:constrainedToSize:lineBreakMode:調整CATextLayer的幀根據這裏返回的大小。

作爲最簡單的方法,選項(b)應該起作用。畢竟,它適用於UILabels。但是,當我將相同的幀計算應用到CATextLayer時,幀總是比預期的或需要的要大一些。

事實證明,CATextLayers和UILabels中的行間距(對於相同的字體和大小)是不同的。其結果是,sizeWithFont(其線間距計算將匹配與UILabels的)不返回CATextLayers預期大小。

這是通過使用印刷一個UILabel相同的文字,作爲針對一個CATextLayer並比較結果進一步證實。第一行中的文本完全重疊(它是相同的字體),但CATextLayer中的行間距僅比UILabel短一點。當(對不起,我不能上傳截圖,現在爲那些我已經有包含機密數據,以及我目前沒有時間,使一個示例項目得到乾淨的截圖,我會上傳到後來爲後人,我有時間)

這是一個奇怪的差異,但我認爲這將有可能通過指定我使用的NSAttributedString的適當屬性來調整CATextLayer中的間距,但似乎並非如此。調查CFStringAttributes.h我找不到可能與行間距有關的單個屬性。

底線:

所以看起來它是不可能在適應它的文字所需要的層場景中使用CATextLayer iOS上。我是對這還是我錯過了什麼?

P.S:

  1. 我想用CATextLayer和NSAttributedString的是因爲要顯示的字符串是要在不同的點不同顏色的原因。我想我必須回去一如既往地用手繪製字符串......當然,總有一種方法是從sizeWithFont中獲取結果以獲得適當的行高。

  2. 濫用「代碼」標籤有點讓文章更具可讀性。

  3. 我無法用'CATextLayer'來標記帖子 - 現在出乎意料地沒有這樣的標籤。如果有足夠聲譽的人碰到這篇文章,請相應標記。

+0

我只是碰到了這個問題......爭奪答案。 – griotspeak 2011-06-02 00:22:57

+0

@所有,如果不清楚,問題嚴格限於垂直調整固定寬度的CATextLayer,對於不同長度/屬性的字符串。 – 2011-10-03 11:27:13

回答

15

試試這個:

- (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子類方法:

- (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。

+0

對不起,這是一段時間,我目前沒有代碼或時間來測試。儘管如此,我一定會回頭看看。與此同時,如果其他人遇到此答案可以驗證它的工作原理,我會將其標記爲「已回答」。 – 2011-12-20 16:31:24

+0

6個月後,我終於再次遇到這個問題。 :)解決方案工作。非常感謝穆斯塔法! – 2012-02-23 05:00:01

-2

本頁面給了我足夠的創建水平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); 
} 
+0

對不起,但我不認爲這回答了這個問題。問題是關於垂直調整CATextLayer的大小來包裝/適合任何字符串,而答案是垂直對齊 - 也就是單行文本。 – 2011-10-03 11:23:05

2

我有一個更簡單的解決方案,可能會或可能不適合你。

如果你沒有做什麼特別的東西與你不能做一個UILabel的CATextLayer,而不是做一個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 
+0

啊,看。正如我的問題的底部所指出的那樣,我特別需要使用CATextLayers來實現他們的格式化功能。否則,UILabel會完美地完成這項工作。無論如何,自從這個問題發佈以來,已經有這麼長時間了,迄今爲止唯一承諾的一個承諾是@穆斯塔法的。悲劇我無法在這麼長的時間內投出一杆。任何人都在爲它做? – 2012-01-28 21:22:42