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

Posted

技术标签:

【中文标题】SwiftUI:如何计算文本视图的宽度?【英文标题】:SwiftUI: how can to calculate the width of a Text view? 【发布时间】:2021-04-20 18:10:16 【问题描述】:

我需要处理未知数量的文本视图(与睡眠期间经过的时间一样多)。每个文本视图只有一个小时,例如文本(“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
    

【问题讨论】:

【参考方案1】:

不能直接回答您的问题,但可能需要研究的方向是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())
            
    

【讨论】:

以上是关于SwiftUI:如何计算文本视图的宽度?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SwiftUI 中嵌入 ForEach 的 HStack 中设置相对宽度?

Swift之深入解析SwiftUI布局如何自定义AlignmentGuides

SwiftUI,使用按钮将文本字段内的值相乘

如何使视图最大。 SwiftUI 中带填充的宽度

SwiftUI 文本视图不显示不可显示的字符

SwiftUI如何对齐大于屏幕宽度的视图