在Swift中为iOS字体描述符添加自定义权重

daolsyd0  于 2023-05-02  发布在  iOS
关注(0)|答案(6)|浏览(320)

这看起来应该非常简单,但无论出于什么原因,它都不起作用。我在SO上读过类似的帖子,似乎字体特征字典有问题?这是一个问题,还是我完全错过了什么?这是我第一次摆弄这样的字体,所以我想可能是后者。
我不想使用常量或提供一个带有“-bold”变体的字体。我想有细粒度控制字体的重量。

let traits = [UIFontWeightTrait : 1.0]
imgFontDescriptor = UIFontDescriptor(fontAttributes: [UIFontDescriptorNameAttribute: "Helvetica"])
imgFontDescriptor = imgFontDescriptor.fontDescriptorByAddingAttributes([UIFontDescriptorTraitsAttribute:traits])
imgTextFont = UIFont(descriptor: imgFontDescriptor!, size: 24.0)

研究:

根据iOS文档,使用数字值应该可以工作(我运行的是iOS 9。2):
UIFont权重属性
作为NSNumber对象的规格化权重值。有效值范围为-1。0到1.0。0的值。0对应于常规或中等字体粗细。也可以使用字体粗细常量来指定特定的粗细;有关可以使用的常量列表,请参见字体粗细。在iOS 7中可用。0及以后

cwxwcias

cwxwcias1#

如果使用现有的fontDescriptor(例如从现有的字体),它可能无法工作,因为显式的'。fontDescriptor中的'name'属性。fontAttributes。
这是一个很好的解决方案(Swift 4):

extension UIFont {
    var bold: UIFont { return withWeight(.bold) }
    var semibold: UIFont { return withWeight(.semibold) }

    private func withWeight(_ weight: UIFont.Weight) -> UIFont {
        var attributes = fontDescriptor.fontAttributes
        var traits = (attributes[.traits] as? [UIFontDescriptor.TraitKey: Any]) ?? [:]

        traits[.weight] = weight

        attributes[.name] = nil
        attributes[.traits] = traits
        attributes[.family] = familyName

        let descriptor = UIFontDescriptor(fontAttributes: attributes)

        return UIFont(descriptor: descriptor, size: pointSize)
    }
}

使用方法:

let baseFont = UIFont(name: "American Typewriter", size: 20)!
let boldFont = baseFont.bold
let semibold = baseFont.semibold
8yparm6h

8yparm6h2#

UIFont(descriptor: imgFontDescriptor!, size: 24.0)返回与描述符匹配的字体。如果它找不到与您的描述匹配的字体,则返回默认字体。因此,您无法手动控制体重。这取决于你使用的字体。如果Font支持该权重,它将返回该权重。
最后,你应该使用[UIFontDescriptorFamilyAttribute: "Helvetica"]。因此,它将根据FamilyName和您的FontWeight确定FontName。
正确的方法是使用Apple lib中的常量:

public let UIFontWeightUltraLight: CGFloat
@available(iOS 8.2, *)
public let UIFontWeightThin: CGFloat
@available(iOS 8.2, *)
public let UIFontWeightLight: CGFloat
@available(iOS 8.2, *)
public let UIFontWeightRegular: CGFloat
@available(iOS 8.2, *)
public let UIFontWeightMedium: CGFloat
@available(iOS 8.2, *)
public let UIFontWeightSemibold: CGFloat
@available(iOS 8.2, *)
public let UIFontWeightBold: CGFloat
@available(iOS 8.2, *)
public let UIFontWeightHeavy: CGFloat
@available(iOS 8.2, *)
public let UIFontWeightBlack: CGFloat*/

您应该使用http://iosfonts.com/来确定该系列名称支持的字体粗细。
如果是Helvetica:

let traits = [UIFontWeightTrait: UIFontWeightLight] // UIFontWeightBold / UIFontWeightRegular
let imgFontDescriptor = UIFontDescriptor(fontAttributes: [UIFontDescriptorFamilyAttribute: "Helvetica"])
imgFontDescriptor = imgFontDescriptor.fontDescriptorByAddingAttributes([UIFontDescriptorTraitsAttribute: traits])
bd1hkmkf

bd1hkmkf3#

Swift 41、简单地做这样的事情:

var descriptor = UIFontDescriptor(name: "Helvetica Neue", size: 24.0)
descriptor = descriptor.addingAttributes([UIFontDescriptor.AttributeName.traits : [UIFontDescriptor.TraitKey.weight : UIFont.Weight.light]])
let font = UIFont(descriptor: descriptor, size: 24.0)
lf3rwulv

lf3rwulv4#

一个简洁的扩展:

extension UIFont {

  /// Returns a new font with the weight specified.
  /// - Parameter weight: The new font weight
  func withWeight(_ weight: UIFont.Weight) -> UIFont {
    let newDescriptor = fontDescriptor.addingAttributes([.traits: [
      UIFontDescriptor.TraitKey.weight: weight]
    ])
    return UIFont(descriptor: newDescriptor, size: pointSize)
  }
}
ni65a41a

ni65a41a5#

以下是Apple在其CareKit框架中对UIFont+Extensions.swift的扩展:
https://github.com/carekit-apple/CareKit/

extension UIFont {
    static func preferredCustomFont(forTextStyle textStyle: TextStyle, weight: Weight) -> UIFont {
        let defaultDescriptor = UIFontDescriptor.preferredFontDescriptor(withTextStyle: textStyle)
        let size = defaultDescriptor.pointSize
        let fontDescriptor = UIFontDescriptor(fontAttributes: [
            UIFontDescriptor.AttributeName.size: size,
            UIFontDescriptor.AttributeName.family: UIFont.systemFont(ofSize: size).familyName
        ])

        // Add the font weight to the descriptor
        let weightedFontDescriptor = fontDescriptor.addingAttributes([
            UIFontDescriptor.AttributeName.traits: [
                UIFontDescriptor.TraitKey.weight: weight
            ]
        ])
        return UIFont(descriptor: weightedFontDescriptor, size: 0)
    }
}
tpxzln5u

tpxzln5u6#

根据答案。@pkamb和@张宏浩
只能使用以下扩展名更新字体粗细

public extension UIFont {
    /// Returns a new font with the weight specified
    ///
    /// - Parameter weight: The new font weight
    func fontWeight(_ weight: UIFont.Weight) -> UIFont {
        let fontDescriptor = UIFontDescriptor(fontAttributes: [
            UIFontDescriptor.AttributeName.size: pointSize,
            UIFontDescriptor.AttributeName.family: familyName
        ])

        // Add the font weight to the descriptor
        let weightedFontDescriptor = fontDescriptor.addingAttributes([
            UIFontDescriptor.AttributeName.traits: [
                UIFontDescriptor.TraitKey.weight: weight
            ]
        ])
        return UIFont(descriptor: weightedFontDescriptor, size: 0)
    }
}

可用于

UIFont.body.fontWeight(.light)

这是为了匹配命名为https://developer.apple.com/documentation/swiftui/text/fontweight(_:)的新SwiftUI API

相关问题