在iOS上显示等比间距的数字(而不是等宽/表格式)

8

我正在iOS中渲染数字(针对7及以上版本),通过将它们存储在NSAttributedString中,使用“drawAtPoint:”进行渲染。我正在使用Helvetica Neue字体。

我注意到这样绘制的数字不是等比例的——所有字形的宽度都相同。即使是瘦弱的“1”占用的空间也与“0”相同。

测试证实了这一点:

for(NSInteger i=0; i<10; ++i)
{
  NSString *iString = [NSString stringWithFormat: @"%d", i];
  const CGSize iSize = [iString sizeWithAttributes: [self attributes]];
  NSLog(@"Size of %d is %f", i, iSize.width);
}

在其他地方:

有关IT技术的内容。
-(NSDictionary *) attributes
{
  static NSDictionary * attributes;
  if(!attributes)
  {
    attributes = @{
                   NSFontAttributeName: [UIFont systemFontOfSize:11],
                   NSForegroundColorAttributeName: [UIColor whiteColor]
                   };
  }
  return attributes;
}

这些结果字形宽度相同,为6.358点。
有没有一些渲染选项可以打开以启用比例数字字形?是否有另一种字体(最好类似于Helvetica Neue)支持比例数字字形(最好内置)?还有其他的选择吗?
谢谢。

关于使用比例和“表格”(等宽字体的另一个术语)“数字”和“数字”的讨论在[链接](http://www.fonts.com/content/learning/fontology/level-3/numbers/proportional-vs-tabular-figures)中进行。通过使用这个术语,我发现了这个[iOS 7字体渲染的链接](http://typographica.org/on-typography/beyond-helvetica-the-real-story-behind-fonts-in-ios-7/),我认为这将让我自己回答这个问题。完成后我会更新。 - Benjohn
这份来自苹果演示文稿的幻灯片链接提供了所需的代码。需要注意的是,要使用这些功能,您必须导入#import <CoreText/CoreText.h>:这是符号定义的地方。 - Benjohn
1个回答

19

iOS 7允许您使用UIFontDescriptor实例指定字体,然后可以从描述符获取一个UIFont实例。

通过使用方法[fontDescriptor fontDescriptorByAddingAttributes:attibutes],可以给定一个UIFontDescriptor,还可以获得更改某些特性的自定义。其中attributes是一个字体属性的NSDictionary

苹果公司在UIFontDescriptor参考文档中记录了这些属性。

从参考文献中,一个特定的字体描述符属性UIFontDescriptorFeatureSettingsAttribute可以让您提供“表示非默认字体特性设置的字典数组。每个字典包含UIFontFeatureTypeIdentifierKeyUIFontFeatureSelectorIdentifierKey。”

UIFontFeatureTypeIdentifierKeys 和 UIFontFeatureSelectorIdentifierKeys 的文档在苹果的字体注册表文档中。等宽数字的具体情况在此幻灯片pdf文件中介绍,因此我只是引用了那个。

此代码将采用现有的UIFont实例,并返回一个带等宽数字的新实例:

// You'll need this somewhere at the top of your file to pull
// in the required constants.
#import <CoreText/CoreText.h>UIFont *const existingFont = [UIFont preferredFontForTextStyle: UIFontTextStyleBody];
UIFontDescriptor *const existingDescriptor = [existingFont fontDescriptor];

NSDictionary *const fontAttributes = @{
 // Here comes that array of dictionaries each containing UIFontFeatureTypeIdentifierKey 
 // and UIFontFeatureSelectorIdentifierKey that the reference mentions.
 UIFontDescriptorFeatureSettingsAttribute: @[
     @{
       UIFontFeatureTypeIdentifierKey: @(kNumberSpacingType),
       UIFontFeatureSelectorIdentifierKey: @(kProportionalNumbersSelector)
      }]
 };

UIFontDescriptor *const proportionalDescriptor = [existingDescriptor fontDescriptorByAddingAttributes: fontAttributes];
UIFont *const proportionalFont = [UIFont fontWithDescriptor: proportionalDescriptor size: [existingFont pointSize]];

如果你愿意的话,可以将此添加为UIFont的一个类别等。

编辑说明:感谢Chris Schwerdt进行改进。


1
+1 不要忘记导入 CoreText 以获取这些常量。 - Tricertops
谢谢Martin,我会修改代码以添加它,因为一开始我被这个问题难住了! - Benjohn
2
UIFontFeatureTypeIdentifierKeyUIFontFeatureSelectorIdentifierKey 的值可以在 SFNTLayoutTypes.h 中找到,该文件进一步引用了 Apple 字体注册表文档 - Chris Schwerdt
2
此外,您可以删除 kCharacterAlternativesType 键。我相信它在那个时间格式示例中被用来将方形冒号字符替换为圆形冒号字符,并且不会影响数字间距。 - Chris Schwerdt
1
只有在使用支持此功能的字体时,此选项才有效。如果您正在使用自定义字体,则可能无法正常工作。字体支持的选项可以通过类似以下代码的方式进行检查:NSLog(@"%@", CTFontCopyFeatures ( (__bridge CTFontRef) myFont)); - Anthony Mattox
显示剩余4条评论

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