自定义安装字体未在 UILabel 中正确显示

Posted

技术标签:

【中文标题】自定义安装字体未在 UILabel 中正确显示【英文标题】:Custom installed font not displayed correctly in UILabel 【发布时间】:2011-07-21 20:18:51 【问题描述】:

我正在尝试使用从 Adob​​e Font Collection Pro Package 获得的 Helvetica Neue Condensed 字体。不幸的是,当我在 UILabel 中使用它时,它似乎绘制不正确。

行高似乎计算正确(我认为),但是当字体显示时,它与边界框的最顶部对齐。我打电话给[myLabel sizeToFit],只调整了宽度来生成这个屏幕截图:

字体的粗体和常规版本都存在同样的问题。我能够从 OSX 中提取一个版本的 Helvetica Neue Bold 并将其放在我的设备上,它显示良好(上图中的绿色背景)。

字体文件或我的代码有什么问题会导致它以这种方式绘制?

【问题讨论】:

我可以创建一个 UIFont 的子类来解决这些问题吗? +1 - 对我来说同样的问题。我已经尝试使用 ZFont 来帮助解决这个问题,它确实有所帮助,但还远远不够。使用这些自定义字体如何解释前导可能有问题(真的不知道 - 但我不得不认为这可能与它有关!)。 嗨!你最终找到解决方案了吗?如果是,请回答您的问题。提前致谢。 不幸的是,不,我没有。而且我再也无法访问导致此问题的原始字体文件。我喜欢 kolyuchiy 的回答。我只希望我能在我的具体情况下对其进行测试。 请注意,这已在 ios7 中修复。 【参考方案1】:

我发布了一个解决方案,涉及修补ttf字体文件here:

这是适用于我的自定义字体的解决方案,它在 UILabel、UIButton 等中存在相同的问题。字体的问题原来是它的 assender 属性与系统字体的值相比太小了。 Ascender 是字体字符上方的垂直空白。要修复您的字体,您必须下载Apple Font Tool Suite 命令行实用程序。然后使用您的字体并执行以下操作:

~$ ftxdumperfuser -t hhea -A d Bold.ttf

这将创建Bold.hhea.xml。用文本编辑器打开它并增加ascender 属性的值。您将不得不进行一些试验以找出最适合您的确切值。就我而言,我将其从 750 更改为 1200。然后使用以下命令行再次运行该实用程序,将您的更改合并回 ttf 文件:

~$ ftxdumperfuser -t hhea -A f Bold.ttf

然后在您的应用中使用生成的 ttf 字体。

【讨论】:

非常感谢您推荐这个工具!它也可以通过编辑“-t name”部分来重命名字体。 你也可以试试Mensis 或 FontForge。这些应用程序也可用于更改上行属性。 你成就了我的一天。几个星期以来,我一直被这个问题困扰。我可以经常使用它! 请注意,通过增加升序,您会增加行间距 - 如果您的应用程序中有多行文本,这可能是问题。 ** 还请参见下面的 JOSEPH LIN 的回答 ** 您应该调整上升器并将 linegap 设置为零,以确保在 iOS 6 和 iOS 7 上都能很好地对齐!【参考方案2】:

所以这是kolyuchiy的答案的修改版本。

我用Glyphs 打开我的字体,然后在没有修改任何内容的情况下将其导出。不知何故,神奇地,垂直对齐问题消失了!

更好的是新字体和sizeWithFont:这样的方法配合得很好,所以它没有Joshua提到的问题。

我使用提到的命令 kolyuchiy 查看了 HHEA 表,并注意到 Glyphs 不仅修改了 ascender,还为我修改了 lineGapnumberOfHMetrics

这是之前的原始数据:

versionMajor="1"
versionMinor="0"
ascender="780"
descender="-220"
lineGap="200"
advanceWidthMax="1371"
minLeftSideBearing="-73"
minRightSideBearing="-52"
xMaxExtent="1343"
caretSlopeRise="1"
caretSlopeRun="0"
caretOffset="0"
metricDataFormat="0"
numberOfHMetrics="751"

之后:

versionMajor="1"
versionMinor="0"
ascender="980"
descender="-220"
lineGap="0"
advanceWidthMax="1371"
minLeftSideBearing="-73"
minRightSideBearing="-52"
xMaxExtent="1343"
caretSlopeRise="1"
caretSlopeRun="0"
caretOffset="0"
metricDataFormat="0"
numberOfHMetrics="748"

所以故事的寓意——不仅要增加上升者,还要修改其他相关的值。

我不是排版专家,所以我无法真正解释原因和方式。如果有人能提供更好的解释,将不胜感激! :)

【讨论】:

在我使用 Glyphs 保存了我再次使用的 TTF 后,该字体在 iOS 6 和 iOS 7 上的行为几乎相同。以前它的基线在 iOS 6 上会错位。 感谢您终于解决了这个问题!显然 iOS 6 尊重 lineGap 属性,而 iOS 7 忽略它。解决的办法是让lineGap为0,让上行者相应变大。这正是 Glyphs 所做的,它适用于 iOS 6 和 iOS 7。 是的。将 lineGap 减少到零 (0) 并离开上升器(在 1991 年)使用 Fedora 提供的免费“Overpass”字体为我解决了这个问题。谢谢大家指导解决方法。适用于 iOS6 和 iOS7。 在多次尝试使用 Glyphs 和 OS X 字体工具失败后,我得出了与 @phatmann 相同的结论。问题是,最好在 OS X 字体工具中使用这个技巧,而不是简单地使用 Glyphs 导出,因为 Glyphs 还会编辑字体的样式名称和后记名称,这会使 xCode 在某些情况下无法找到字体。【参考方案3】:

iOS 6 尊重字体的 lineGap 属性,而 iOS 7 忽略它。因此,只有行间距为 0 的自定义字体才能在两个操作系统中正常工作。

解决的办法是让lineGap为0,让上行线相应变大。根据上面的answer,一种解决方案是从 Glyphs 导入和导出。但请注意,该应用的未来版本可能会修复此“错误”。

一个更强大的解决方案是根据post 自己编辑字体。具体来说,

    安装 OS X 字体工具。 将字体规格转储到文件中:ftxdumperfuser -t hhea -A d YOUR_FONT.ttf 在编辑器中打开转储文件。 通过添加lineGap 属性的值来编辑ascender 属性。例如,如果 lineGap 为 200,ascender 为 750,则将 ascender 设为 950。 将lineGap 设置为0。 将更改合并到字体中:ftxdumperfuser -t hhea -A f YOUR_FONT.ttf

完成此操作后,您可能需要相应地调整 UI。

【讨论】:

【参考方案4】:

对于那些运行 OS X El Capitan 并来到此线程的人,您可能已经注意到 Apple 字体工具套件不再兼容(至少目前是这样)。

但是您仍然可以使用免费的字体编辑软件FontForge 执行 kolyuchiyJoseph Lin 描述的更改。

使用 FontForge 打开字体并在顶部菜单中选择 Element,然后转到 Font Info > OS/2 > Metrics。您想在此处编辑 HHEad Line Gap 和 HHead Ascent Offset 值。

完成必要的编辑后,您可以在文件 > 生成字体中导出字体并选择正确的字体格式

【讨论】:

【参考方案5】:

我们的一种自定义字体也遇到了同样的问题。我们还通过编辑字体升序属性“修复”了这个问题。但是,我们发现这会产生其他问题和布局问题。例如,当使用我们的升序编辑字体时,根据标签高度动态设置单元格高度会爆炸。

我们最终做的是更改 UIButton contentEdgetInsets 属性。

yourButton.contentEdgeInsets = UIEdgeInsetsMake(-10, 0, 0, 0);

不确定哪种方法更好,但只是想分享另一种解决问题的方法。

【讨论】:

同意。 Assender 属性修复不是理想的解决方案 嗨 Joshua,我刚刚发布了一个方法,可以解决您提到的问题。简而言之,随着上升器,还需要修改一些属性。【参考方案6】:
    在此处下载并安装 Apple 的字体工具:https://developer.apple.com/downloads/index.action?q=font(下载链接在底部) 打开终端并 cd 到字体所在的位置 运行此命令:ftxdumperfuser -t hhea -A d MY_FONT_NAME.ttf 现在您有了一个包含一些字体属性的 xml 文件,请在文本编辑器中对其进行编辑 搜索“lineGap”属性并将其值加 200 保存xml文件 运行此命令:ftxdumperfuser -t hhea -A f MY_FONT_NAME.ttf 删除xml文件 在 iOS 6 上尝试配置的字体,看看是否更好看。 如果需要,您可以返回到步骤 3 并添加/减去“lineGap”属性。 (我最终在我的配置中添加了 250)

【讨论】:

【参考方案7】:

感谢answer 我解决了 Glyphs 的问题,但有点不同。

我用 Glyphs 打开了我的字体(也适用于 Glyphs mini)并在那里找到了这个部分(来自 Glyphs mini,要到达那里,请按右上角的 i 按钮):

只需删除所有这些对齐区域(或其中一些),它就会解决这个问题。 非常适合我。

【讨论】:

【参考方案8】:

从标签文本创建属性文本是我的解决方法。这是一个扩展:

extension UILabel 
    /// You can call with or without param values; without will use default 2.0
    func setLineSpacing(lineSpacing: CGFloat = 2.0, lineHeightMultiple: CGFloat = 2.0) 
        guard let labelText = self.text else  return 
        let paragraphStyle = NSMutableParagraphStyle()
        paragraphStyle.lineSpacing = lineSpacing
        paragraphStyle.lineHeightMultiple = lineHeightMultiple
        let attributedString:NSMutableAttributedString
        if let labelattributedText = self.attributedText 
            attributedString = NSMutableAttributedString(attributedString: labelattributedText)
         else 
            attributedString = NSMutableAttributedString(string: labelText)
        
        // (Swift 4.2 and above) Line spacing attribute
        attributedString.addAttribute(NSAttributedString.Key.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))
        self.attributedText = attributedString
    

对于我的自定义字体,我得到了我需要的结果:

self.myLabel.setLineSpacing(lineSpacing: 1.2, lineHeightMultiple: 1.2)

这通过使用本机提供的NSMutableParagraphStyle() 来工作,其中包含行高和间距属性(如果您不编写标签,也可以在情节提要中作为@IBOutlet 属性访问)。

【讨论】:

【参考方案9】:

你试过Core Text吗?我在通过 Core Text 渲染自定义字体方面取得了一些成功,但我不知道它是否适合您的情况。

【讨论】:

我可以确认核心文本没有这个问题。【参考方案10】:

我使用了https://github.com/fonttools/fonttools - 非常易于使用且免费。就我而言,'hhea' 表中的 'ascender'=1000 和 'lineGap'=0 的变化起到了作用。

基于 Trevor Harmon https://medium.com/@thetrevorharmon/how-to-use-apples-font-tools-to-tweak-a-font-a386600255ae的文章

【讨论】:

【参考方案11】:

如果您在使用这些命令行实用程序时遇到问题,请尝试在窗口中使用 fontcreator。并从其设置菜单中更改字体分配器。

【讨论】:

【参考方案12】:

对于因找不到命令错误而在 Mac OS Mojave 上努力使用 ftxdumperfuser(kolyuchiy 答案)的任何人:

从 Apple 下载字体工具包。发现他们在 https://developer.apple.com/download/more/?q=font,为 XCode 11。 挂载dmg文件 输入磁盘映像 cd /Volumes/macOS\ 字体\工具 将包解压到您选择的文件夹:pkgutil --expand-full macOS\ Font\ Tools.pkg ~/font-tools CLI 工具现在在 ~/font-tools/FontCommandLineTools.pkg/Payload 中可用,您 可以将文件夹添加到您的路径 (export PATH="$PATH:$HOME/font-tools/FontCommandLineTools.pkg/Payload"),或将 utils 复制到您的 bin 文件夹。

【讨论】:

【参考方案13】:

我的 Sprite Kit 游戏中的标志性“FontAwesome”字体也有类似的问题。 将 SKLabelNode 的 SKLabelVerticalAlignmentMode 属性设置为 .Center 对我有用。

myLabel.verticalAlignmentMode = SKLabelVerticalAlignmentMode.Center

只是想分享一下,以防有人遇到同样的问题。

【讨论】:

以上是关于自定义安装字体未在 UILabel 中正确显示的主要内容,如果未能解决你的问题,请参考以下文章

SetCurrentConsoleFontEx() 不适用于自定义安装的字体

在 InstallShield for DPI 中自定义安装过程

自定义通知,如 Inshorts

Visual Studio 2017中应用程序的自定义安装程序

office2016怎么自定义安装

Install4j 绕过了自定义安装步骤