在 iPhone 上,如何计算给定点大小的字符大小(以像素为单位)?
8 回答
磅值定义为 1/72 英寸。也就是说,72 磅字体从最低下降到最高上升大约 1 英寸。所以 72pt 字体中字形的最大高度约为 1 英寸。
Apple 的 iphone 技术规格页面声称 iPhone目前的分辨率为每英寸 163 像素。所以 72 个点是 163 个像素,或者每个点大约 2.2639 个像素。请记住,每个字形的高度和宽度都不同,因此这是对大小的非常粗略的估计。通常,基线之间的距离会比字体的磅值大一点,这样文本行就不会相互碰撞。
如果您需要精确的测量值(并且您可能需要),那么您需要使用字体度量信息实际测量字体字形。您可以通过使用NSString 的 UIKit 附加功能来做到这一点,它可以让您测量特定字符串在屏幕上呈现时的大小。
我们的图形艺术家在某些设备上非常具体地使用像素大小而不是点大小。下面的函数将根据像素大小返回字体。它使用蛮力方法来查找壁橱字体,然后缓存结果,因此下次返回会非常快。我总是很欣赏有关如何使此代码变得更好的评论。我将此函数用作名为 utils 的类中的静态类成员。您可以轻松粘贴到您正在使用的任何类中。希望对您有所帮助。
/** return a font as close to a pixel size as possible
example:
UIFont *font = [Utils fontWithName:@"HelveticaNeue-Medium" sizeInPixels:33];
@param fontName name of font same as UIFont fontWithName
@param sizeInPixels size in pixels for font
*/
+(UIFont *) fontWithName:(NSString *) fontName sizeInPixels:(CGFloat) pixels {
static NSMutableDictionary *fontDict; // to hold the font dictionary
if ( fontName == nil ) {
// we default to @"HelveticaNeue-Medium" for our default font
fontName = @"HelveticaNeue-Medium";
}
if ( fontDict == nil ) {
fontDict = [ @{} mutableCopy ];
}
// create a key string to see if font has already been created
//
NSString *strFontHash = [NSString stringWithFormat:@"%@-%f", fontName , pixels];
UIFont *fnt = fontDict[strFontHash];
if ( fnt != nil ) {
return fnt; // we have already created this font
}
// lets play around and create a font that falls near the point size needed
CGFloat pointStart = pixels/4;
CGFloat lastHeight = -1;
UIFont * lastFont = [UIFont fontWithName:fontName size:.5];\
NSMutableDictionary * dictAttrs = [ @{ } mutableCopy ];
NSString *fontCompareString = @"Mgj^";
for ( CGFloat pnt = pointStart ; pnt < 1000 ; pnt += .5 ) {
UIFont *font = [UIFont fontWithName:fontName size:pnt];
if ( font == nil ) {
NSLog(@"Unable to create font %@" , fontName );
NSAssert(font == nil, @"font name not found in fontWithName:sizeInPixels" ); // correct the font being past in
}
dictAttrs[NSFontAttributeName] = font;
CGSize cs = [fontCompareString sizeWithAttributes:dictAttrs];
CGFloat fheight = cs.height;
if ( fheight == pixels ) {
// that will be rare but we found it
fontDict[strFontHash] = font;
return font;
}
if ( fheight > pixels ) {
if ( lastFont == nil ) {
fontDict[strFontHash] = font;
return font;
}
// check which one is closer last height or this one
// and return the user
CGFloat fc1 = fabs( fheight - pixels );
CGFloat fc2 = fabs( lastHeight - pixels );
// return the smallest differential
if ( fc1 < fc2 ) {
fontDict[strFontHash] = font;
return font;
} else {
fontDict[strFontHash] = lastFont;
return lastFont;
}
}
lastFont = font;
lastHeight = fheight;
}
NSAssert( false, @"Hopefully should never get here");
return nil;
}
您无法可靠地将点转换为像素,因为 ppi(每英寸点数)会因显示器而异。读一读;
也就是说,有些人整理了一些参考表和计算器,可以帮助您入门;
http://www.unitconversion.org/typography/postscript-points-to-pixels-x-conversion.html
获取给定字体和大小的像素高度的最简单方法是在 NSString 上使用 boundingRect 方法。(我在@"Ap"
这里使用以确保它包含一个下降器和一个上升器。)
- (CGFloat)heightForFont:(UIFont *)font
{
NSStringDrawingContext *context = [[NSStringDrawingContext alloc] init];
CGRect boundingRect = [@"Ap" boundingRectWithSize:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX) options:NSStringDrawingUsesFontLeading attributes:@{NSFontAttributeName:font} context:context];
return boundingRect.size.height;
}
当我弄清楚它们时,我会添加它们:
具有 12pt systemFont 的 sizedToFit UILabel 高 15px。
您可以通过渲染 aNSAttributedString
并获取其大小来动态计算像素大小。
extension UIFont {
var pixelSize: CGFloat {
let string = "AWZgjpq"
let attributedString = NSMutableAttributedString(string: string)
attributedString.setAttributes([.font: self], range: NSRange(location: 0, length: string.count))
return attributedString.size().height
}
}
进一步的优化可能是添加查找字典和缓存结果和/或使测试字符串不是变量(但调用本身非常快)。此外,如果您的字体有一些非常不规则的字形,您也可以将它们添加到测试字符串中。
用法:let pixelSize = label.font.pixelSize