如何使用 SwiftUI 显示分数

问题描述 投票:0回答:3

我试图在 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)
    }
}
ios xcode swiftui swiftui-text
3个回答
3
投票

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()
)

产生这个结果:

the string


0
投票

在此基础上,这里有一个没有弃用的版本,它采用

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)
    }
}

0
投票

您可以通过用 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
}
© www.soinside.com 2019 - 2024. All rights reserved.