使表内的内容的确切大小

  • 本文关键字: swift swiftui swiftui-sheet
  • 更新时间 :
  • 英文 :


假设我在一个工作表中有一个自定义视图,就像这样

VStack {
Text("Title")
Text("Some very long text ...")
}
.padding()
.presentationDetents([.height(250)])

我如何获得VStack的确切高度并将其传递给presentationents修饰符,以便工作表的高度正好是内部内容的高度?

使用@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 var defaultValue: CGFloat = .zero
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = nextValue()
}
}

您可以使用GeometryReaderPreferenceKey读取大小,然后将其写入状态变量。在我的示例中,我存储了整个大小,但您可以调整它以仅存储高度,因为这可能是您需要的唯一参数。

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() }
}

更可重用

struct InnerHeightPreferenceKey: PreferenceKey {
static var defaultValue: CGFloat = .zero
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) { value = nextValue() }
}
extension View {
func fixedInnerHeight(_ sheetHeight: Binding<CGFloat>) -> some View {
padding()
.background {
GeometryReader { proxy in
Color.clear.preference(key: InnerHeightPreferenceKey.self, value: proxy.size.height)
}
}
.onPreferenceChange(InnerHeightPreferenceKey.self) { newHeight in sheetHeight.wrappedValue = newHeight }
.presentationDetents([.height(sheetHeight.wrappedValue)])
}
}
struct ExampleView: 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 ...")
}
.fixedInnerHeight($sheetHeight)
}
}
}

1。Сreate一个Сustom修饰符,返回任何视图的高度(这是一个非常有用的修饰符,您很可能会在其他地方使用):

struct GetHeightModifier: ViewModifier {
@Binding var height: CGFloat
func body(content: Content) -> some View {
content.background(
GeometryReader { geo -> Color in
DispatchQueue.main.async {
height = geo.size.height
}
return Color.clear
}
)
}
}

2。使用自定义修饰符来获取高度

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()
.modifier(GetHeightModifier(height: $sheetHeight))
.presentationDetents([.height(sheetHeight)])
}
}
}
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))
}
}

}

相关内容

  • 没有找到相关文章

最新更新