16

这似乎应该很容易,但无论出于何种原因,它都不起作用。我在 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):

UIFontWeightTrait

作为 NSNumber 对象的标准化权重值。有效值范围是 -1.0 到 1.0。0.0 的值对应于常规或中等字体粗细。您还可以使用字体粗细常量来指定特定的粗细;有关可以使用的常量列表,请参阅字体粗细。在 iOS 7.0 及更高版本中可用。

4

5 回答 5

22

如果您使用现有的 fontDescriptor(例如来自现有字体),它可能无法正常工作,因为 fontDescriptor.fontAttributes 中有显式的“.name”属性。

对我有用的解决方案(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
于 2018-03-19T19:31:01.253 回答
15

UIFont(descriptor: imgFontDescriptor!, size: 24.0)正在返回与描述符匹配的字体。如果找不到与您的描述匹配的字体,则返回默认字体。因此,您无法手动控制体重。这取决于您使用的字体。如果字体支持该重量,它将返回该重量。

还有一件事,你应该使用[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])
于 2016-01-04T05:25:09.117 回答
13

使用 Swift 4.1,只需执行以下操作:

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)
于 2018-05-19T22:17:32.697 回答
8

一个简洁的扩展:

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)
  }
}
于 2020-01-14T05:00:26.103 回答
4

这是 AppleUIFont+Extensions.swift在其 CareKit 框架中的扩展:

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)
    }
}
于 2020-05-30T09:49:25.763 回答