SwiftUI:如何计算文本视图的宽度?

问题描述

我需要考虑的文本视图数量未知(睡眠期间经过的小时数)。每个文本视图只有一个小时,例如文本(“12”),文本(“1”)等

我需要知道所有合并的小时文本视图的宽度,以便我可以相应地从整体几何图形中减去空间。下面是一个 widthOfString 函数,它可能与 UIKit 一起使用,但似乎没有在 SwiftUI 中计算出正确的大小。我怎样才能做到这一点?

示例用法

  Spacer()
    .frame(width: CGFloat(hourAsDate.timeIntervalSince(hoursBetweenSleepStartAndEnd[(hoursBetweenSleepStartAndEnd.firstIndex(of: hourAsDate) ?? 0) - 1]) / totalSleepSeconds)  * calculateSpaceOfHourText())
  Text("\(calendar.component(.hour,from: hourAsDate))")
    .font(Font.system(size: 13.0))
  Spacer()
    .frame(width: CGFloat(sleepEndDate.timeIntervalSince(hourAsDate) / totalSleepSeconds)  * calculateSpaceOfHourText())

我的辅助函数和扩展:

       //helper
    private func calculateSpaceOfHourText() -> CGFloat {
    
    //The idea here is to try to add up all the space that is taken up by hour Text views and subtract it from the total with of geometry
    
        var hoursToUseForCalculationOfSpace = hoursBetweenSleepStartAndEnd
        
        if hoursBetweenSleepStartAndEnd.first ?? Date() <= sleepStartDate {
            hoursToUseForCalculationOfSpace.removeFirst()
        }
        
        if hoursBetweenSleepStartAndEnd.last ?? Date() >= sleepEndDate {
            hoursToUseForCalculationOfSpace.removeLast()
        }
        return (proxy.size.width - hoursToUseForCalculationOfSpace.map { calendar.component(.hour,from: $0) }.map { "\($0)".widthOfString(usingFont: UIFont.systemFont(ofSize: 13,weight: .regular)) }.reduce(0,+))
    }
}

extension String {
   func widthOfString(usingFont font: UIFont) -> CGFloat {
        let fontAttributes = [NSAttributedString.Key.font: font]
        let size = self.size(withAttributes: fontAttributes)
        //print("THIS width = \(size.width)")
        return size.width
    }
}

解决方法

不能直接回答您的问题,但可能需要研究的方向是 PreferenceKey 协议与 GeometryReader 的结合。例如,以下代码在背景中绘制一个 RoundedRectangle 及其修改的视图的高度:

struct HeightPreferenceKey: PreferenceKey {
    static var defaultValue: [CGFloat] = []
    
    static func reduce(value: inout [CGFloat],nextValue: () -> [CGFloat]) {
        value.append(contentsOf: nextValue())
        
    }
    
    typealias Value = [CGFloat]
}

struct HeightPreferenceViewSetter: View {
    var body: some View {
        GeometryReader { geometry in
            RoundedRectangle(cornerRadius: 13)
                .fill(Color.gray)
                .preference(key: HeightPreferenceKey.self,value: [geometry.size.height]) 
              }
    }
}
struct HeightModifier: ViewModifier {
    func body(content: Content) -> some View {
        content
            .background(HeightPreferenceViewSetter())
            
    }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...