自定义安装的字体未在 UILabel 中正确显示
Posted
技术标签:
【中文标题】自定义安装的字体未在 UILabel 中正确显示【英文标题】:Custom installed font not displayed correctly in UILabel 【发布时间】:2011-07-21 20:18:51 【问题描述】:我正在尝试使用从 Adobe 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
,还为我修改了lineGap
和numberOfHMetrics
。
这是之前的原始数据:
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 执行 kolyuchiy 和 Joseph 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 答案)的任何人:
export PATH="$PATH:$HOME/font-tools/FontCommandLineTools.pkg/Payload"
),或将 utils 复制到您的 bin
文件夹。
【讨论】:
【参考方案13】:我的 Sprite Kit 游戏中的标志性“FontAwesome”字体也有类似的问题。 将 SKLabelNode 的 SKLabelVerticalAlignmentMode 属性设置为 .Center 对我有用。
myLabel.verticalAlignmentMode = SKLabelVerticalAlignmentMode.Center
只是想分享一下,以防有人遇到同样的问题。
【讨论】:
以上是关于自定义安装的字体未在 UILabel 中正确显示的主要内容,如果未能解决你的问题,请参考以下文章
SetCurrentConsoleFontEx() 不适用于自定义安装的字体
自定义 UILabel 视图未在 Interface Builder 中更新其框架
在 InstallShield for DPI 中自定义安装过程