【问题标题】:UIFont: How to use Stylistic Alternate character?UIFont:如何使用文体替代字符?
【发布时间】:2020-04-15 07:26:16
【问题描述】:

在我的应用程序中,我想将 stylistic alternate font 用于 'a' 而不是 system font

附上screenshot,解释字体的不同渲染。

如何为 UILabelUITextView 启用此行为,以便它呈现正确的 One Storey 'a'?

我确实找到了 YouTube video link ,它解释了这一点,但他使用的是 custom font 并且它是硬编码的。我只想使用system font,但要使用这个替代字符。

我也许可以用custom character 硬编码UILabel,我不确定,因为我想使用System font。我不想使用custom Font。可编辑的UITextView 怎么样?我们如何让它在用户输入时使用备用a

【问题讨论】:

  • 这是什么应用的截图?我一直在寻找类似的东西来探索字体功能。
  • 可能是文本编辑。这就是我为此目的所使用的。
  • 是的。这是字体面板的排版部分。好处是您可以更改一个功能并立即在文档中使用它来查看它的作用。
  • 它是 MacOS 标准字体面板的一部分,进入设置并选择排版。
  • @RobNapier 所以基本上可能 any 使用内置 Cocoa 字体面板的 Cocoa 应用程序都有这个。我只是求助于 TextEdit,因为它是每个人都有的纯 Cocoa 应用程序。

标签: ios swift uifont typography


【解决方案1】:

这是一个名为“Alternative Stylistic Sets”的字体功能,您可以使用 CoreText 进行配置。请记住,并非所有字体都有此选项,但系统字体有。但是,您需要弄清楚您想要哪个替代设置。

首先,创建你感兴趣的字体:

import CoreText
import UIKit

let baseFont = UIFont.systemFont(ofSize: 72)

然后打印出它的特征:

print(CTFontCopyFeatures(baseFont)!)

找到关于替代风格集的部分,特别是您想要的集,“一层楼:”

    {
    CTFeatureTypeIdentifier = 35;
    CTFeatureTypeName = "Alternative Stylistic Sets";
    CTFeatureTypeSelectors =         (
                    {
            CTFeatureSelectorIdentifier = 2;
            CTFeatureSelectorName = "Straight-sided six and nine";
        },
                    {
            CTFeatureSelectorIdentifier = 4;
            CTFeatureSelectorName = "Open four";
        },
                    {
            CTFeatureSelectorIdentifier = 6;
            CTFeatureSelectorName = "Vertically centered colon";
        },
                    {
            CTFeatureSelectorIdentifier = 10;
            CTFeatureSelectorName = "Vertically compact forms";
        },
                    {
            CTFeatureSelectorIdentifier = 12;
            CTFeatureSelectorName = "High legibility";
        },
                    {
            CTFeatureSelectorIdentifier = 14;
            CTFeatureSelectorName = "One storey a";
        },
        ...

重要的数字是选择器(CTFeatureSelectorIdentifier),14。用它你可以创建一个新的字体描述符和新字体:

let descriptor = CTFontDescriptorCreateCopyWithFeature(
    baseFont.fontDescriptor,
    kStylisticAlternativesType as CFNumber,
    14 as CFNumber)

如果更方便的话,你也可以直接在 UIKit 中执行此操作:

let settings: [UIFontDescriptor.FeatureKey: Int] = [
    .featureIdentifier: kStylisticAlternativesType,
    .typeIdentifier: 14
]

let descriptor = baseFont.fontDescriptor.addingAttributes([.featureSettings: [settings]])

(请注意,.featureIdentifier 是“CTFeatureTypeIdentifier”而.typeIdentifier 是“CTFeatureSelectorIdentifier”,这有点令人惊讶。)

然后你可以创建一个新字体(零大小意味着保持大小不变​​):

let font = UIFont(descriptor: descriptor, size: 0)

您可以在任何接受 UIFont 的地方使用它。

【讨论】:

  • “有点令人惊讶的事实”我自己称之为错误。 :)
  • @matt 我从这个信念开始(最初将其称为答案中的错误),但我不确定。无论如何我打开了一个反馈(虽然我不希望他们回复或修复它)。
  • 是的,我的已经开了好几年了。
  • @RobNapier 感谢您完美的深入解释。这确实有效!
【解决方案2】:

假设您知道它的名称,下面是一个扩展,可简化为字体选择替代样式集的过程:

示例用法:

guard let updatedFont = font.withAlternativeStylisticSet(withName: "Alternate y") else {
    fatalError("Alternative stylistic set is undefined")
}

UIFont 扩展:

import UIKit
import CoreText

extension UIFont {
    
    /// Returns the font, applying an alternative stylistic style set.
    func withAlternativeStylisticSet(withName name: String) -> UIFont? {
        guard let identifier = alternativeStylisticSetIdentifier(withName: name) else {
            return nil
        }
        
        let settings: [UIFontDescriptor.FeatureKey: Int] = [
            .featureIdentifier: kStylisticAlternativesType,
            .typeIdentifier: identifier
        ]
        
        let fontDescriptor = self.fontDescriptor.addingAttributes([.featureSettings: [settings]])
        return UIFont(descriptor: fontDescriptor, size: 0)
    }
    
    /// Returns the identifier for an alternative stylistic set
    private func alternativeStylisticSetIdentifier(withName selectorName: String) -> Int? {
        guard let ctFeatures = CTFontCopyFeatures(self) else {
            return nil
        }
        
        let features = ctFeatures as [AnyObject] as NSArray
        for feature in features {
            if let featureDict = feature as? [String: Any] {
                if let typeName = featureDict[kCTFontFeatureTypeNameKey as String] as? String {
                    if typeName == "Alternative Stylistic Sets" {
                        if let featureTypeSelectors = featureDict[kCTFontFeatureTypeSelectorsKey as String] as? NSArray {
                            for featureTypeSelector in featureTypeSelectors {
                                if let featureTypeSelectorDict = featureTypeSelector as? [String: Any] {
                                    if let name = featureTypeSelectorDict[kCTFontFeatureSelectorNameKey as String] as? String, let identifier = featureTypeSelectorDict[kCTFontFeatureSelectorIdentifierKey as String] as? Int {
                                        if name == selectorName {
                                            return identifier
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
        
        return nil
    }

}

【讨论】:

  • 对于荒谬的嵌套级别,我深表歉意。
猜你喜欢
  • 2012-01-21
  • 2018-05-19
  • 2013-04-07
  • 2015-10-24
  • 2012-06-20
  • 2019-03-02
  • 1970-01-01
  • 2012-02-11
相关资源
最近更新 更多