NSString* str = @"hello kitty, would you tell me why do you want to go to shanghai?";
//这一句,我要怎么才能知道上面文字分行之后的确切高度,而不是给定一个固定值200?
[str drawInRect:NSMakeRect(10, 20, 100, 200) withAttributes:nil];
[str release];
解决方案 »
- iphone 获取经纬度
- 如何分享内容到Twitter。
- bar butoon item 有问
- 求助:iOS手机app内设置手机可以做ap有开放的api否?
- UIViewController切换问题
- 为什么新创建的AppID都默认打上GameCenter和In-App-Purchase能力权限啊?
- 求个正则式替换字符串的方法
- sencha architect3 中怎样实现使用listpaging以及pullrefresh插件做的分页?
- 请问怎么确定一个app是不是原生开发
- iOS(编辑内容被键盘遮盖)ScrollView里的包含了TextField&&TextView(用了监听的方法)
- ios 使用ffmpeg对h264进行解码的问题
- 服了 关于cocos2d 用nsmutablearray读plist的问题。
此方法可以计算出文字放到一个固定的(constrainedToSize)大小里面的宽高;
比如你的:CGSize strSize = [str sizeWithFont:[UIFont systemFontOfSize:16]
constrainedToSize:CGSizeMake(100, CGFLOAT_MAX)
lineBreakMode:UILineBreakModeCharacterWrap];
///////////////////////////////////////////
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上的处理显然效率更好。
stackoverflow 上有一个类 似的讨论,不过没考虑到iOS的区别
//以下代码没有正确计算出文字的高度...大家看看哪里出错了?
- (int)getAttributedStringHeightWithString:(NSAttributedString*)string WidthValue:(int)width {
int h = 10000; //[string length] * 40;
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)string); //string为要计算高度的NSAttributedString
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, CGRectMake(0, 0, width, h)); //这里的高要设置足够大
CTFrameRef textFrame = CTFramesetterCreateFrame(framesetter, CFRangeMake(0, 0), path, NULL);
CGPathRelease(path);
CFRelease(framesetter);
NSArray* linesArray = (NSArray*)CTFrameGetLines(textFrame);
NSUInteger count = [linesArray count];
if(count <= 0) {
CFRelease(textFrame);
return 0;
}
CGPoint origins[count];
CTFrameGetLineOrigins(textFrame, CFRangeMake(0, 0), origins);
CGFloat line_y = origins[count - 1].y; //最后一行line的原点y坐标
CGFloat ascent, descent, leading;
CTLineRef line = (CTLineRef)[linesArray objectAtIndex: [linesArray count] - 1];
CTLineGetTypographicBounds(line, &ascent, &descent, &leading);
CGFloat total_height = h - line_y + ascent + descent + leading + 1; //+1为了纠正descent转换成int小数点后舍去的值
CFRelease(textFrame);
return total_height;
}
- (void)drawRect:(NSRect)dirtyRect {
NSString* str = @"hello kitty, would you tell me why do you want to go to shanghai? 真心伤不起\n\
楞个圾有圾和在有了上国有和国因为相关爆发\n正常情况下,计算行高只需要ascent+descent+leading即可。\n\
在这个略有不同的情况下,leading的值会出现偏差,导致算出来的结果是错误的。如果不管行距,\n\
ascent+descent计算出来的Glyph的高度还是正确的。这样就有了第一步在创建用于绘图的CFAttributedStringRef时,\n\
除了设置字体,多设置一个CTParagraphStyleRef,其中特别应该确定行距kCTParagraphStyleSpecifierLineSpacing。\n\
在计算这里时,先逐行计算ascent+descent,累加起来,再加上一个行数*之前设置好的行距,这样算出来的就是这些文本的实\n\
际高度,CTLineGetTypographicBounds返回的结果是宽度,这样就可得到文本实际填充面积的Rect了";
NSAttributedString* string = [[NSAttributedString alloc] initWithString:str];
int h = [self getAttributedStringHeightWithString:string WidthValue:200];
[str drawInRect:NSMakeRect(0, 0, 200, h) withAttributes:nil];
[string release];
[str release];
}
NSString *labelString = @"hello kitty, would you tell me why do you want to go to shanghai? 真心伤不起\n\
楞个圾有圾和在有了上国有和国因为相关爆发正常情况下,计算行高只需要ascent+descent+leading即可。\n\
在这个略有不同的情况下,leading的值会出现偏差,导致算出来的结果是错误的。如果不管行距,\n\
ascent+descent计算出来的Glyph的高度还是正确的。这样就有了第一步在创建用于绘图的CFAttributedStringRef时,\n\
除了设置字体,多设置一个CTParagraphStyleRef,其中特别应该确定行距kCTParagraphStyleSpecifierLineSpacing。\n\
在计算这里时,先逐行计算ascent+descent,累加起来,再加上一个行数*之前设置好的行距,这样算出来的就是这些文本的实\n\
际高度,CTLineGetTypographicBounds返回的结果是宽度,这样就可得到文本实际填充面积的Rect了";
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
[NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]], NSFontAttributeName,
//[NSColor redColor], NSForegroundColorAttributeName,
//[NSColor yellowColor], NSBackgroundColorAttributeName,
nil];
NSSize labelSize = [labelString sizeWithAttributes:attributes];
NSRect labelRect = NSMakeRect(0, 0, labelSize.width, labelSize.height);
[labelString drawInRect:labelRect withAttributes:attributes];
///////////////////////////
hello kitty, would you tell me why do you want to go to shanghai? 真心伤不起
楞个圾有圾和在有了上国有和国因为相关爆发正常情况下,计算行高只需要ascent+descent+leading即可。
在这个略有不同的情况下,leading的值会出现偏差,导致算出来的结果是错误的。如果不管行距,
ascent+descent计算出来的Glyph的高度还是正确的。这样就有了第一步在创建用于绘图的CFAttributedStringRef时,
除了设置字体,多设置一个CTParagraphStyleRef,其中特别应该确定行距kCTParagraphStyleSpecifierLineSpacing。
在计算这里时,先逐行计算ascent+descent,累加起来,再加上一个行数*之前设置好的行距,这样算出来的就是这些文本的实
际高度,CTLineGetTypographicBounds返回的结果是宽度,这样就可得到文本实际填充面积的Rect了//////////////////////////
没有在200处分行,实事上我需要分行,效果如下,怎么实现呢?///////////////////////
hello kitty, would you tell me why do you
want to go to shanghai? 真心伤不起
楞个圾有圾和在有了上国有和国因为相关
爆发正常情况下,计算行高只需要ascent+
descent+leading即可。
在这个略有不同的情况下,leading的值会
出现偏差,导致算出来的结果是错误的。如果不
管行距,
ascent+descent计算出来的Glyph的高度
还是正确的。这样就有了第一步在创建用于绘图
的CFAttributedStringRef时,
除了设置字体,多设置一个
CTParagraphStyleRef,其中特别应该确定行距
kCTParagraphStyleSpecifierLineSpacing。
在计算这里时,先逐行计算ascent+
descent,累加起来,再加上一个行数*之前设置
好的行距,这样算出来的就是这些文本的实
际高度,
CTLineGetTypographicBounds返回的结果是宽
度,这样就可得到文本实际填充面积的Rect了