SwiftUI: заставить лист отображать заголовок содержимого или полный контент
Я хотел бы иметь лист SwiftUI, который показывает либо заголовок, либо полное содержимое. Требуется iOS 16 — это нормально.
Я уже получаю правильные два измеренных значения высоты в презентации.
import Foundation
import SwiftUI
struct ContentView: View {
@State private var showSheet = false
@State private var headerSize: CGSize = .zero
@State private var overallSize: CGSize = .zero
var body: some View {
Button("View sheet") {
showSheet = true
}
.sheet(isPresented: $showSheet) {
Group {
VStack(alignment: .leading) {
Text("Header")
.background(
GeometryReader { geometryProxy in
Color.clear
.preference(key: HeaderSizePreferenceKey.self, value: geometryProxy.size)
}
)
Text("")
Text("Some very long text ...")
Text("Some very long text ...")
Text("Some very long text ...")
Text("Some very long text ...")
Text("Some very long text ...")
Text("Some very long text ...")
Text("Some very long text ...")
Text("Some very long text ...")
} // VStack
.padding()
.background(
//measure without spacer
GeometryReader { geometryProxy in
Color.clear
.preference(key: SizePreferenceKey.self, value: geometryProxy.size)
}
)
Spacer()
} // Group
.onPreferenceChange(SizePreferenceKey.self) { newSize in
overallSize.height = newSize.height
}
.onPreferenceChange(HeaderSizePreferenceKey.self) { newSize in
headerSize.height = newSize.height
}
.presentationDetents([
.height(headerSize.height),
.height(overallSize.height)
]
)
} // sheet content
}
}
struct HeaderSizePreferenceKey: PreferenceKey {
static var defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) { value = nextValue() }
}
struct SizePreferenceKey: PreferenceKey {
static var defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) { value = nextValue() }
}
struct MySheet_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Этот код основан на идеях из статьи «Создание листа с точным размером содержимого внутри».
Это почти работает. Это полный размер содержимого:
Это размер содержимого заголовка:
Что я могу сделать, чтобы в последнем случае отображалась верхняя часть содержимого («Заголовок»), а не центр содержимого?