Rah*_*Bir 16 swift swiftui swiftui-sheet
假设我在工作表中有一个自定义视图,如下所示
VStack {
Text("Title")
Text("Some very long text ...")
}
.padding()
.presentationDetents([.height(250)])
Run Code Online (Sandbox Code Playgroud)
如何获取 VStack 的准确高度并将其传递给presentationDetents 修改器,以便工作表的高度恰好等于内部内容的高度?
Rah*_*Bir 18
使用@jnpdx提出的一般想法,包括一些更新,例如读取覆盖层的大小而不是背景,以下是对我有用的方法:
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 let defaultValue: CGFloat = .zero
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
}
Run Code Online (Sandbox Code Playgroud)
小智 10
1. \xd0\xa1创建一个 \xd0\xa1ustom 修饰符,返回任何视图的高度(这是一个非常有用的修饰符,您很可能会在其他地方使用):
\nstruct GetHeightModifier: ViewModifier {\n @Binding var height: CGFloat\n\n func body(content: Content) -> some View {\n content.background(\n GeometryReader { geo -> Color in\n DispatchQueue.main.async {\n height = geo.size.height\n }\n return Color.clear\n }\n )\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n2. 使用自定义修改器获取高度。
\nstruct ContentView: View {\n @State private var showSheet = false\n @State private var sheetHeight: CGFloat = .zero\n\n var body: some View {\n Button("Open sheet") {\n showSheet = true\n }\n .sheet(isPresented: $showSheet) {\n VStack {\n Text("Title")\n Text("Some very long text ...")\n }\n .padding()\n .fixedSize(horizontal: false, vertical: true)\n .modifier(GetHeightModifier(height: $sheetHeight))\n .presentationDetents([.height(sheetHeight)])\n }\n }\n}\n\nRun Code Online (Sandbox Code Playgroud)\n
您可以使用GeometryReader和PreferenceKey读取大小,然后将其写入状态变量。在我的示例中,我存储了整个尺寸,但您可以调整它以仅存储高度,因为这可能是您需要的唯一参数。
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() }
}
Run Code Online (Sandbox Code Playgroud)