像素字体大小

39

在iPhone上,如何根据给定的点大小计算字符的像素大小?

8个回答

65

点大小被定义为1英寸的1/72。也就是说,72点字体的高度从最低处到最高处大约为1英寸。所以,在72pt字体中,字形的最大高度约为1英寸。

苹果的iPhone技术规格页面声称iPhone目前的分辨率为每英寸163像素。因此,72点等于163像素,约为每点2.2639像素。但请记住,每个字形的高度和宽度都会有所不同,因此这只是一个非常粗略的尺寸估计。通常,基线之间的距离会比字体的点大小稍大一些,以避免文本行相互碰撞。

如果你需要准确的测量(而你可能需要),那么你需要使用字体度量信息来实际测量字形。你可以使用NSString的UIKit补充来实现这一点,这将让你在屏幕上渲染特定字符串时测量其大小。


10
值得一提的是,iPhone并不是唯一的iPhone-OS设备。iPod touch的分辨率为160 dpi。因此,已经有iPhone-OS设备的分辨率不相同。如果苹果公司将来将其加倍、推出平板电脑、手表或其他什么设备,并且您假定像素数量固定不变,那么您就会遇到麻烦。要具备分辨率无关性,因为如果没有这样的话,您的应用程序将在未来某个时候崩溃。 - Peter Hosey
6
嘿,猜猜看——苹果发布了一款具有不同dpi的平板电脑 :-) - philsquared
另外,苹果推出了具有更高DPI的手机和iPod...您的应用程序肯定会崩溃:) - Richard J. Ross III
2
嘿,你猜怎么着 - 苹果为他们的iPod Nano推出了一款手表表带,所以他们在技术上也推出了一款手腕表。 :) - Tony Bolero
1
@philsquared 这并不重要,因为系统假定您始终在编写72 dpi的代码,然后在运行时自动进行缩放。 - Sabobin
显示剩余2条评论

32
为了使iPhone4上的字体大小(以点为单位)与Photoshop中的字体大小(以点为单位)相匹配,您需要将Photoshop文档设置为144dpi。我进行了一些测试,发现这个分辨率可以产生1:1的结果。
步骤:
  • 在iPhone4上截取“设置»通用»辅助功能»大号字体”的屏幕截图
  • 在Photoshop中打开该截图
  • 关闭“重新采样图像”,将分辨率从72dpi更改为144dpi
  • 在Photoshop中重新输入字体(以点为单位),以匹配屏幕截图中的大小
我已经尝试过多种不同的分辨率,包括上面提到的163dpi,发现144dpi可以产生1:1的结果。我还在一个本地应用程序上进行了测试,其中我知道点大小,144dpi也能匹配。

3
每个空格增加125%似乎非常合适。 - user207616
1
不确定它是否回答了问题,但这正是我在寻找的,你应该最终将这个答案移动到“如何在Photoshop和iOS/xcode中匹配字体大小”。 - Hugues BR
这对我非常有效。当然,它适用于1x的分辨率而不是2x(Retina)。因此,例如,在iPad布局上,使用768x1024的分辨率和144 dpi来匹配字体大小。 - Mark Nugent
144适用于iPhone 4s和5,但似乎要匹配iPhone 6和6+需要在Photoshop中具有216dpi的分辨率。 - Ben Thielker
链接已失效。 - Max von Hippel

5

我们的图形设计师在某些设备上使用像素大小而不是点大小非常具体。 下面的函数将返回基于像素大小的字体。 它使用暴力方法来查找最接近的字体,但然后缓存结果,所以下次返回将非常快。我总是很感激关于如何改进此代码的评论。我将此函数用作名为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;
}

3
我相信你正在寻找UIFontNSString扩展,它可以让你在给定UIFont的情况下计算字符串的大小。
这里是链接 具体来说,就是使用sizeWithFont方法。

4
链接已损坏。 - shim

1
使用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;
}

1

4
我很确定人们不会把显示器插入他们的iPhone。 - Mike Daniels
3
如果苹果改变iPhone的分辨率但不改变物理屏幕尺寸,那么像素密度将发生变化,因此在旧的像素密度下进行的任何点对像素的转换都将无效。 - Mathew
MatW - 我同意这是需要考虑的事情,但在那种情况下,我很可能还需要重新测试我的应用程序。我想很多应用程序都会出现问题。 - Ian1971
此外,我认为提到的NSString UIKit扩展可以解决这个问题。 - Ian1971
1
Mike Daniels:没关系。并非所有的iPhone-OS设备都具有相同的分辨率;iPod touch的分辨率稍低。此外,苹果有可能在未来添加应用程序通过连接到基座的电视或显示器进行传输的功能。 - Peter Hosey
1
Peter Hosey不知道他在说什么。所有iPhone OS设备在像素方面具有相同的基础度量标准。如果未来的任何iOS设备没有这样的度量标准,我会吃我的帽子。 - mxcl

0

您可以通过渲染NSAttributedString并获取其大小来动态计算像素大小。

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


0
我会在弄清楚后加上它们: 使用12pt系统字体的sizedToFit UILabel高度为15px。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接