我试图在 SwiftUI 文本中表示分母大于 9 的分数。
我可以使用单独的元素并应用偏移量来实现这一点,但是随着分数的动态变化,这会有点混乱。
有没有办法使用 attributeText 来做到这一点?
我遇到了带有已弃用方法的 UIFont 扩展,想知道是否有任何类似的东西可以与 SwiftUI 一起使用:
extension UIFont {
static func fractionFont(ofSize pointSize: CGFloat) -> UIFont {
let systemFontDesc = UIFont.systemFont(ofSize: pointSize).fontDescriptor
let fractionFontDesc = systemFontDesc.addingAttributes(
[
UIFontDescriptor.AttributeName.featureSettings: [
[
UIFontDescriptor.FeatureKey.featureIdentifier: kFractionsType,
UIFontDescriptor.FeatureKey.typeIdentifier: kDiagonalFractionsSelector,
], ]
] )
return UIFont(descriptor: fractionFontDesc, size:pointSize)
}
}
UIFont
与 CTFont
是免费桥接的,这意味着您可以通过说 UIFont
将 CTFont
投射到 as CTFont
。 SwiftUI 的 Font
有一个接受 CTFont
的初始化器。
因此,使用您发布的
fractionFont(ofSize:)
方法,这个操场代码:
PlaygroundPage.current.setLiveView(
Text("The fraction 21/345 is rendered nicely.")
.font(Font(UIFont.fractionFont(ofSize: UIFont.systemFontSize) as CTFont))
.padding()
)
产生这个结果:
在此基础上,这里有一个没有弃用的版本,它采用
UIFont.TextStyle
作为参数,允许您简单地执行此操作:
Text("1/4")
.font(.fraction(.headline))
以下是您需要的扩展:
extension UIFont {
static func fractionFont(ofSize pointSize: CGFloat) -> UIFont {
let systemFontDesc = UIFont.systemFont(ofSize: pointSize).fontDescriptor
let featureSettings: [UIFontDescriptor.FeatureKey: Int] = [
.type: kFractionsType,
.selector: kDiagonalFractionsSelector,
]
let attributes = [
UIFontDescriptor.AttributeName.featureSettings: [
featureSettings
]
]
let fractionFontDesc = systemFontDesc.addingAttributes(attributes)
return UIFont(descriptor: fractionFontDesc, size: pointSize)
}
}
extension Font {
static func fraction(_ style: UIFont.TextStyle) -> Font {
let preferredFont = UIFont.preferredFont(forTextStyle: style)
let size = preferredFont.pointSize
return Font(UIFont.fractionFont(ofSize: size) as CTFont)
}
}
您可以通过用 Unicode 上标/下标字符替换数字来避免需要
AttributedString
和 UIKit(并了解上下文的 TextStyle
)。该解决方案的灵感来自于Objective-C 对类似问题的回答。
let superscriptDigits: [Character : Character] = ["0":"⁰", "1":"¹", "2":"²", "3":"³", "4":"⁴", "5":"⁵", "6":"⁶", "7":"⁷", "8":"⁸", "9":"⁹", "-":"⁻"];
let subscriptDigits : [Character : Character] = ["0":"₀", "1":"₁", "2":"₂", "3":"₃", "4":"₄", "5":"₅", "6":"₆", "7":"₇", "8":"₈", "9":"₉", "-":"₋"];
func fractionString(numerator: Int, denominator: Int) -> String {
let superscriptNumerator = numerator.description.map { superscriptDigits[$0, default: $0] }
let subscriptDenominator = denominator.description.map { subscriptDigits[$0, default: $0] }
return superscriptNumerator + "⁄" + subscriptDenominator
}
print(fractionString(numerator: 12, denominator: 34))
// "¹²⁄₃₄"
上述函数将显示分子/分母内的任何负号。如果您想在负分数之外显示减号,您可以像这样更改函数(并从字典中删除减号):
func fractionString(numerator: Int, denominator: Int) -> String {
let superscriptNumerator = abs(numerator).description.map { superscriptDigits[$0, default: $0] }
let subscriptDenominator = abs(denominator).description.map { subscriptDigits[$0, default: $0] }
let isNegative = (numerator < 0 && denominator >= 0) || (numerator >= 0 && denominator < 0)
return (isNegative ? "−" : "") + superscriptNumerator + "⁄" + subscriptDenominator
}