在 Swift/SwiftUI 中更改十进制数的字体大小

Posted

技术标签:

【中文标题】在 Swift/SwiftUI 中更改十进制数的字体大小【英文标题】:change the fontsize of the decimal number in Swift/ SwiftUI 【发布时间】:2021-08-26 09:10:34 【问题描述】:

所以我需要使小数位小于实际数字,我将在下面告诉你我的意思。

这是我的代码:

import SwiftUI

struct BalanceDetailsView: View 
    //MARK: - PROPERTIES
    var balance: Float
    var balanceString: String 
        return balance.formattedWithSeparator
    
    //MARK: - BODY
    var body: some View 
        VStack
            HStack
                    Text(balanceString)
                        .font(.custom(K.fonts.gilroyBold, size: 24))
                        .multilineTextAlignment(.center)
                        .padding(.top)
             
            //:VSTACK
        //:HSTACK
    


struct BalanceDetailsView_Previews: PreviewProvider 
    static var previews: some View 
        BalanceDetailsView(balance: 43678)
            .previewLayout(.sizeThatFits)
    




//Formatter extension i used to get this code
extension Formatter 
    static let withSeparator: NumberFormatter = 
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal

        // minimum decimal digit, eg: to display 2 as 2.00
        formatter.minimumFractionDigits = 2

        // maximum decimal digit, eg: to display 2.5021 as 2.50
        formatter.maximumFractionDigits = 2
        
        return formatter
    ()


extension Numeric 
    var formattedWithSeparator: String  Formatter.withSeparator.string(for: self) ?? "" 

Result I get Result I need

【问题讨论】:

【参考方案1】:

当您知道字符串的确切格式时,例如在这种情况下最小字符串长度为 4("0.00") ,您可以安全地使用 dropLastdropFirst

我建议将 2 移动到 priceFractionDigits 常量以减少代码中常量的使用。

然后你可以使用字符串连接,它会根据基线对齐Text

struct BalanceText: View 
    var balance: Float
    var balanceString: String 
        return balance.formattedWithSeparator
    
    
    var body: some View 
        Text(balanceString.dropLast(priceFractionDigits))
            .font(.system(size: 24))
            +
            Text(balanceString.dropFirst(balanceString.count - priceFractionDigits))
            .font(.system(size: 18))
    


private let priceFractionDigits = 2

extension Formatter 
    static let withSeparator: NumberFormatter = 
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal

        // minimum decimal digit, eg: to display 2 as 2.00
        formatter.minimumFractionDigits = priceFractionDigits

        // maximum decimal digit, eg: to display 2.5021 as 2.50
        formatter.maximumFractionDigits = priceFractionDigits
        
        return formatter
    ()

用法

BalanceText(balance: balance)

【讨论】:

【参考方案2】:

这是在 SwiftUI 3(ios 15、macOS 12 等)中使用新 AttributedString 的示例

var balanceString: AttributedString 
    var attributedString = AttributedString(balance.formattedWithSeparator)
    guard let separator = Formatter.withSeparator.decimalSeparator else  return attributedString 

    if let range = attributedString.range(of: separator) 
        attributedString[attributedString.startIndex...attributedString.index(beforeCharacter: range.lowerBound)]
            .font = Font.largeTitle
        attributedString[attributedString.index(afterCharacter: range.lowerBound)..<attributedString.endIndex]
            .font = Font.caption
    

    return attributedString

我在这里使用了一些内置字体样式,但应该很容易替换。另请注意,由于我们在此处设置了.font 属性,因此应将其从Text 中删除

【讨论】:

【参考方案3】:

您可以将Text+ 运算符连接在一起。

我稍微改变了您使用 NumberFormatter 的方式,所以它被区域设置的正确十进制字符分割。

struct BalanceDetailsView: View 
    private let wholeNumberPart: String
    private let decimalNumberPart: String

    init(balance: Double) 
        (wholeNumberPart, decimalNumberPart) = balance.formattedSplittingBySeparator
    

    var body: some View 
        Text(wholeNumberPart).font(.system(size: 24)) +
        Text(decimalNumberPart).font(.system(size: 16))
    



extension Numeric 
    var formattedSplittingBySeparator: (whole: String, decimal: String) 
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.minimumFractionDigits = 2
        formatter.maximumFractionDigits = 2
        let str = formatter.string(for: self) ?? "0\(formatter.decimalSeparator!)00"
        let split = str.components(separatedBy: formatter.decimalSeparator)
        let whole = (split.first ?? "0") + formatter.decimalSeparator
        let decimal = split.count == 2 ? split[1] : "00"
        return (whole: whole, decimal: decimal)
    

用法:

BalanceDetailsView(balance: 43678)

结果:

【讨论】:

【参考方案4】:

您可以用小数分隔符分割字符串,并以零间距 HStack 显示各个部分。

struct BalanceView : View 
    let balance : Float
    
    var body: some View 
        let components = balance
                        .formattedWithSeparator
                        .components(separatedBy: Formatter.withSeparator.decimalSeparator)
        HStack(alignment: .firstTextBaseline, spacing: 0) 
            Text(components[0])
            if components.count > 1 
                Text(".")
                Text(components[1])
                    .font(.title)
            
        
        .font(.largeTitle)
        .multilineTextAlignment(.center)
        .padding(.top)
    

用您的自定义字体替换字体


在你的环境中你可以使用它

struct BalanceDetailsView: View 
    //MARK: - PROPERTIES
    var balance: Float
    
    //MARK: - BODY
    var body: some View 
        VStack
           BalanceView(balance: balance)
        //:VSTACK
    

【讨论】:

以上是关于在 Swift/SwiftUI 中更改十进制数的字体大小的主要内容,如果未能解决你的问题,请参考以下文章

79.C++ 中的字面值常量

如何让 TextField 值更改触发 SwiftUI 中另一条数据的更新?

在 Swift + SwiftUI 中处理错误的好习惯

在 Swift 5/Swiftui 中重构 MapView(没有 Coordinators / UIViewRepresentables)

二进制计数器的模值是啥意思?呀

Swift:SwiftUI中MapKit的使用体验