SwiftUI: как рассчитать ширину текстового представления?
У меня неизвестное количество текстовых просмотров, которые мне нужно учитывать (столько часов, сколько проходит во время сна). Каждое текстовое представление длится всего один час, например текст («12»), текст («1») и т. Д.
Мне нужно знать ширину всех объединенных часовых текстовых представлений, чтобы я мог соответственно вычесть из общей геометрии пространство. Ниже приводится
Пример использования:
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())
}
}