Let's say I have a custom view inside of a sheet, something like this
VStack {
Text("Title")
Text("Some very long text ...")
}
.padding()
.presentationDetents([.height(250)])
How can I get the exact height of the VStack and pass it to the presentationDetents modifier so that the height of the sheet is exactly the height of the content inside?
CodePudding user response:
You can use a GeometryReader
and PreferenceKey
to read the size and then write it to a state variable. In my example, I store the entire size, but you could adjust it to store just the height, since it's likely that that is the only parameter you need.
struct ContentView: View {
@State private var showSheet = false
@State private var size: CGSize = .zero
var body: some View {
Button("View sheet") {
showSheet = true
}
.sheet(isPresented: $showSheet) {
VStack {
Text("Title")
Text("Some very long text ...")
}
.padding()
.background(
GeometryReader { geometryProxy in
Color.clear
.preference(key: SizePreferenceKey.self, value: geometryProxy.size)
}
)
.onPreferenceChange(SizePreferenceKey.self) { newSize in
size.height = newSize.height
}
.presentationDetents([.height(size.height)])
}
}
}
struct SizePreferenceKey: PreferenceKey {
static var defaultValue: CGSize = .zero
static func reduce(value: inout CGSize, nextValue: () -> CGSize) { value = nextValue() }
}
CodePudding user response:
struct ContentView: View {
@State private var showingSheet = false
let heights = stride(from: 0.1, through: 1.0, by: 0.1).map { PresentationDetent.fraction($0) }
var body: some View {
Button("Show Sheet") {
showingSheet.toggle()
}
.sheet(isPresented: $showingSheet) {
Text("Random text ")
.presentationDetents(Set(heights))
}
}
}
CodePudding user response:
Using the general idea made by @jnpdx including some updates such as reading the size of the overlay instead of the background, here is what works for me:
struct ContentView: View {
@State private var showSheet = false
@State private var sheetHeight: CGFloat = .zero
var body: some View {
Button("Open sheet") {
showSheet = true
}
.sheet(isPresented: $showSheet) {
VStack {
Text("Title")
Text("Some very long text ...")
}
.padding()
.overlay {
GeometryReader { geometry in
Color.clear.preference(key: InnerHeightPreferenceKey.self, value: geometry.size.height)
}
}
.onPreferenceChange(InnerHeightPreferenceKey.self) { newHeight in
sheetHeight = newHeight
}
.presentationDetents([.height(sheetHeight)])
}
}
}
struct InnerHeightPreferenceKey: PreferenceKey {
static var defaultValue: CGFloat = .zero
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
}