你好,歡迎來到IOS教程網

 Ios教程網 >> IOS訊息 >> 關於IOS >> IOS core text計算文本高度及最大寬度

IOS core text計算文本高度及最大寬度

編輯:關於IOS
IOS core text計算文本高度及最大寬度
- (CGSize) measureFrame: (CTFrameRef) frame forContext: (CGContext *) cgContext
{//frame為排版後的文本
CGPathRefframePath =CTFrameGetPath(frame);
CGRectframeRect =CGPathGetBoundingBox(framePath);
CFArrayReflines =CTFrameGetLines(frame);
CFIndexnumLines =CFArrayGetCount(lines);
CGFloatmaxWidth =0;
CGFloattextHeight =0;
// Now run through each line determining the maximum width of all the lines.
// We special case the last line of text. While we've got it's descent handy,
// we'll use it to calculate the typographic height of the text as well.
CFIndexlastLineIndex = numLines -1;
for(CFIndexindex =0; index < numLines; index++)
{
CGFloatascent, descent, leading, width;
CTLineRefline = (CTLineRef)CFArrayGetValueAtIndex(lines, index);
width =CTLineGetTypographicBounds(line, &ascent,  &descent, &leading);
if(width > maxWidth)
{
maxWidth = width;
}
if(index == lastLineIndex)
{
// Get the origin of the last line. We add the descent to this
// (below) to get the bottom edge of the last line of text.
CGPointlastLineOrigin;
CTFrameGetLineOrigins(frame,CFRangeMake(lastLineIndex,1), &lastLineOrigin);
// The height needed to draw the text is from the bottom of the last line
// to the top of the frame.
textHeight = CGRectGetMaxY(frameRect) - lastLineOrigin.y+ descent;
}
}
// For some text the exact typographic bounds is a fraction of a point too
// small to fit the text when it is put into a context. We go ahead and round
// the returned drawing area up to the nearest point.  This takes care of the
// discrepencies.
returnCGSizeMake(ceil(maxWidth),ceil(textHeight));
}
使用Core Text計算一段文本繪制在屏幕上之後的高度 Core Text提供了一系列方便的函數,可以很容易的把文本繪制在屏幕上,對於一個Frame來說,一般並不需要擔心文本的排列問題,這些Core Text的函數都可以直接搞定,只要給他一個大小合適的CGRect就可以。

但,在某些情況下,我們還希望知道這段文本在繪制之後,對應繪制的字體字號設置,在屏幕上實際占用了多大面積。舉例來說,有文本段落a,屏幕大小rect,通常做法是以rect創建path,然後創建CTFramesetter,再然後創建CTFrame,最後用CTFrameDraw畫出來,這時候,往往文本段落占用的實際面積會小於rect,這時候就有必要獲得這段文本所占用的真正面積。

最理想的情況是使用

double CTLineGetTypographicBounds( CTLineRef line, CGFloat* ascent, CGFloat* descent, CGFloat* leading );

這是Core Text提供的函數,傳入CTLine,就會得到這一行的ascent,descent和leading,在OSX上通常可以工作的很好,但是在iOS(iPhone/iPad)上這個函數的結果略有不同。

正常情況下,計算行高只需要ascent+descent+leading即可。在這個略有不同的情況下,leading的值會出現偏差,導致算出來的結果是錯誤的。如果不管行距,ascent+descent計算出來的Glyph的高度還是正確的。

這樣就有了第一步

在創建用於繪圖的CFAttributedStringRef時,除了設置字體,多設置一個CTParagraphStyleRef,其中特別應該確定行距kCTParagraphStyleSpecifierLineSpacing。在計算這裡時,先逐行計算ascent+descent,累加起來,再加上一個行數*之前設置好的行距,這樣算出來的就是這些文本的實際高度,CTLineGetTypographicBounds返回的結果是寬度,這樣就可得到文本實際填充面積的Rect了。

但是這還是有問題,因為OSX上和iOS處理不同,所以事實上iOS的模擬器和真機的最終效果是不一樣的,這樣調試程序很麻煩。
於是還需要第二步

在最終往頁面上繪制的時候,不再用CTFrameDraw來一次繪制全部,而是使用CTLineDraw逐行畫,在畫之前,先用CGContextSetTextPosition來設置好每行文本的位置。這樣就保證了在任何平台上繪制效果一致。

問題就解決了。

CoreText在OS X和iOS上實現有很多細節區別,比如說,對CTRun的劃分方式也不一樣,在iOS上劃分出來的Run數量比OSX上少很多,是按照字體劃分的Run,按照文檔出來,這是正確的,但OSX上是一個字一個Run這樣劃分的,和文檔不符。iOS上的處理顯然效率更好。

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved