问题描述
我需要考虑的文本视图数量未知(睡眠期间经过的小时数)。每个文本视图只有一个小时,例如文本(“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())
}
}