2011-03-20 42 views
0

我需要一個像CTFrameGetVisibleStringRange這樣的方法,它可以給我一個以換行符模式(即自動換行)提供給定大小的文本。例如,我有一長串文本..並且我有一個給定的矩形來繪製包裹在文本中的文本,但是無論文本在何處被創建,我都會繼續將其呈現在另一個離開它的區域。所以我需要一個像這樣的方法:CTFrameGetVisibleStringRange相當於iOS編程嗎?

NSString * text = "The lazy fox jumped over the creek"; 
[text drawAtPoint:CGPointMake(0, 0) forWidth:20 withFont:[UIFont fontWithName:@"Arial" size:10] lineBreakMode:UILineBreakModeWordWrap]; 
// now I do I know how much it drew before it stopped rendering? 

任何有什麼想法?

**編輯:請參閱我的解決方案。

回答

2

我有一個類似的問題,我用了Mike發佈的解決方案。

但是,事實證明,trimToWord經常給我一些太多的單詞,超出了指定的UILabel大小。我發現,如果我將while循環運算符更改爲> =而不僅僅是>,則它完美運行。

我還添加了幾個ivars(chopIndexremainingBody),我用它來獲取剩餘的字符串,以便在下一個UILabel中顯示它。

這是我使用的解決方案。

-(NSString*) rewindOneWord:(NSString*) str{ 
    // rewind by one word 
    NSRange lastspace = [str rangeOfString:@" " options:NSBackwardsSearch]; 
    if (lastspace.location != NSNotFound){ 
     int amount = [str length]-lastspace.location; 
     chopIndex -= amount; 
     return [str substringToIndex:lastspace.location]; 
    }else { 
     // no spaces, lets just rewind 2 characters at a time 
     chopIndex -= 2; 
     return [str substringToIndex:[str length]-2]; 
    } 
} 

// returns only how much text it could render with the given stipulations 
-(NSString*) trimToWord:(NSString*)str sizeConstraints:(CGSize)availableSize withFont:(UIFont*)font{ 
    if(str == @"") 
     return str; 

    CGSize measured = [str sizeWithFont:font constrainedToSize:CGSizeMake(availableSize.width, CGFLOAT_MAX) lineBreakMode:UILineBreakModeWordWrap]; 
    // 'guess' how much we will need to cut to save on processing time 
    float choppedPercent = (((double)availableSize.height)/((double)measured.height)); 
    if(choppedPercent >= 1.0){ 
     //entire string can fit in availableSize 
     remainingBody = @""; 
     return str; 
    } 

    chopIndex = choppedPercent*((double)[str length]); 
    str = [str substringToIndex:chopIndex]; 
    // rewind to the beginning of the word in case we are in the middle of one 
    do{ 
     str = [self rewindOneWord:str]; 
     measured = [str sizeWithFont:font constrainedToSize:availableSize lineBreakMode:UILineBreakModeWordWrap]; 
    }while(measured.height>=availableSize.height); 

    //increment past the last space in the chopIndex 
    chopIndex++; 

    //update the remaining string 
    remainingBody = [remainingBody substringFromIndex:chopIndex]; 

    return str; 
} 
+0

不錯的工作teradyl – 2011-04-26 23:57:20

+0

我已經爲您解決了這個問題的答案,因爲您已經改進了我的解決方案。謝謝@teradyl – 2013-05-15 01:52:08

0

我不認爲,有CTFrameGetVisibleStringRange替代,雖然我們可以得到相同的使用下面的方法。

- (CGSize)sizeWithFont:(UIFont *)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode 

蘋果文檔

http://developer.apple.com/library/ios/#documentation/uikit/reference/NSString_UIKit_Additions/Reference/Reference.html

編輯:下面的代碼顯示我的做法

NSString * text = "The lazy fox jumped over the creek"; 

NSArray* m_Array = [text componentsSeparatedByCharactersInSet: [NSCharacterSet characterSetWithCharactersInString:@" "]]; 

CGSize mySize = CGSizeMake(300,180); 
NSMutableString* myString = [[NSMutableString alloc] initWithString:@""]; 

//The below code till the end of the while statement could be put in separate function. 

CGSize tempSize = CGSizeMake(0,0); 
NSInteger index = 0 ; 
do 
{ 
     [myString appendString:[m_Array objectAtIndex:index]]; 
     tempSize = [myString sizeWithFont:myfont constrainedToSize: 
     CGSizeMake(mySize.width, CGFLOAT_MAX) lineBreakMode: UILineBreakModeWordWrap]; 
     index++; 

}while(tempSize.height < mySize.height && index <= [m_Array count]) 

//Remove the string items from m_Array till the (index-1) index, 

[self RemoveItems:m_Array tillIndex:(index-1)];//Plz define you own 

//you have the myString which could be fitted in CGSizeMake(300,180); 


//Now start with remaining Array items with the same way as we have done above. 
} 
+0

這給了我一個大小..我需要知道什麼部分的字符串被繪製。 – 2011-03-20 07:04:40

+0

@Mike Simmons:對,通過使用這個功能,你可以檢查最少的一組單詞來填充給定的矩形。 – Jhaliya 2011-03-20 07:07:30

+0

@Mike Simmons:檢查我更新了我的答案。 – Jhaliya 2011-03-20 07:40:32

1

這裏是一個解決方案。這相當快。它'猜測'在哪裏先砍,然後逐字回滾。 sizewithFont調用相當昂貴,所以這個初始'猜測'步驟很重要。主要方法是trimToWord:sizeConstraints:withFont。

隨意評論我如何能改善這一點。

-(NSString*) rewindOneWord:(NSString*) str{ 
    // rewind by one word 
    NSRange lastspace = [str rangeOfString:@" " options:NSBackwardsSearch]; 
    if (lastspace.location != NSNotFound){ 
     int amount = [str length]-lastspace.location; 
     return [str substringToIndex:lastspace.location]; 
    }else { 
     // no spaces, lets just rewind 2 characters at a time 
     return [str substringToIndex:[str length]-2]; 
    } 
} 

// returns only how much text it could render with the given stipulations 
-(NSString*) trimToWord:(NSString*) str sizeConstraints:(CGSize) avail withFont:(UIFont*) font{ 
    CGSize measured = [str sizeWithFont:font constrainedToSize:CGSizeMake(avail.width, 1000000) lineBreakMode:UILineBreakModeWordWrap]; 
    // 'guess' how much we will need to cut to save on processing time 
    float choppedPercent = (((double)avail.height)/((double)measured.height)); 
    if (choppedPercent >= 1.0){ 
     return str; 
    } 

    int chopIndex = choppedPercent*((double)[str length]); 
    str = [str substringToIndex:chopIndex]; 
    // rewind to the beginning of the word in case we are in the middle of one 
    str = [self rewindOneWord:str]; 
    measured = [str sizeWithFont:font constrainedToSize:avail lineBreakMode:UILineBreakModeWordWrap]; 
    while (measured.height>avail.height){ 
     str = [self rewindOneWord:str]; 
     measured = [str sizeWithFont:font constrainedToSize:avail lineBreakMode:UILineBreakModeWordWrap]; 
    } 
    return str; 
}