SwiftUI - VStack 中的 ExpandableView
SwiftUI - ExpandableView inside VStack
我正在尝试在 VStack 中创建多个带有动画的可扩展视图。我有以下代码:
struct ContentView: View {
var body: some View {
NavigationView {
ScrollView {
VStack {
ExpandableView(headerTitle: "First")
ExpandableView(headerTitle: "Second")
Spacer()
}
}
}
}
}
以及 ExpandableView:
struct ExpandableView: View {
let headerTitle: String
@State private var collapsed: Bool = true
var body: some View {
Button(
action: {
self.collapsed.toggle()
},
label: {
VStack(spacing: 2) {
ZStack {
Rectangle()
.fill(.gray)
VStack {
Text("\(headerTitle) Header")
if !collapsed {
HStack {
Text("Text A")
Text("Text B")
}
}
}
}
.frame(height: collapsed ? 52 : 80)
ZStack(alignment: .top) {
Rectangle()
.fill(.gray)
.frame(height: 204)
VStack {
Text("Content A")
Text("Content B")
Text("Content C")
}
}
.frame(maxHeight: collapsed ? 0 : .none)
.clipped()
}
}
)
.buttonStyle(PlainButtonStyle())
.animation(.easeOut, value: collapsed)
}
}
结果是这样的:
如您所见,我打开最后一个 expandableView 是否正确打开。但是,如果我在第二个关闭时打开第一个,它实际上会打开第二个。如果第二个已经打开,它只会正确打开第一个。似乎 VStack 本身没有正确呈现。任何想法为什么会这样?
感谢您的帮助。
我可能就是按钮的工作方式。这是一个更清洁的解决方案:
struct ExpandableView: View {
let headerTitle: String
@State private var collapsed: Bool = true
var body: some View {
VStack(spacing: 2) {
Button(
action: {
withAnimation(.easeOut){
self.collapsed.toggle()
}
},
label: {
VStack {
Text("\(headerTitle) Header")
if !collapsed {
HStack {
Text("Text A")
Text("Text B")
}
}
}.frame(maxWidth: .infinity)
})
.buttonStyle(.borderedProminent)
.tint(.gray)
if(!self.collapsed) {
VStack {
Divider().background(.black)
Text("Content A")
Text("Content B")
Text("Content C")
}
}
Spacer()
}
.frame(height: collapsed ? 52 : 204)
.frame(maxWidth: .infinity)
.background(.gray)
.padding()
}
}
我正在尝试在 VStack 中创建多个带有动画的可扩展视图。我有以下代码:
struct ContentView: View {
var body: some View {
NavigationView {
ScrollView {
VStack {
ExpandableView(headerTitle: "First")
ExpandableView(headerTitle: "Second")
Spacer()
}
}
}
}
}
以及 ExpandableView:
struct ExpandableView: View {
let headerTitle: String
@State private var collapsed: Bool = true
var body: some View {
Button(
action: {
self.collapsed.toggle()
},
label: {
VStack(spacing: 2) {
ZStack {
Rectangle()
.fill(.gray)
VStack {
Text("\(headerTitle) Header")
if !collapsed {
HStack {
Text("Text A")
Text("Text B")
}
}
}
}
.frame(height: collapsed ? 52 : 80)
ZStack(alignment: .top) {
Rectangle()
.fill(.gray)
.frame(height: 204)
VStack {
Text("Content A")
Text("Content B")
Text("Content C")
}
}
.frame(maxHeight: collapsed ? 0 : .none)
.clipped()
}
}
)
.buttonStyle(PlainButtonStyle())
.animation(.easeOut, value: collapsed)
}
}
结果是这样的:
如您所见,我打开最后一个 expandableView 是否正确打开。但是,如果我在第二个关闭时打开第一个,它实际上会打开第二个。如果第二个已经打开,它只会正确打开第一个。似乎 VStack 本身没有正确呈现。任何想法为什么会这样? 感谢您的帮助。
我可能就是按钮的工作方式。这是一个更清洁的解决方案:
struct ExpandableView: View {
let headerTitle: String
@State private var collapsed: Bool = true
var body: some View {
VStack(spacing: 2) {
Button(
action: {
withAnimation(.easeOut){
self.collapsed.toggle()
}
},
label: {
VStack {
Text("\(headerTitle) Header")
if !collapsed {
HStack {
Text("Text A")
Text("Text B")
}
}
}.frame(maxWidth: .infinity)
})
.buttonStyle(.borderedProminent)
.tint(.gray)
if(!self.collapsed) {
VStack {
Divider().background(.black)
Text("Content A")
Text("Content B")
Text("Content C")
}
}
Spacer()
}
.frame(height: collapsed ? 52 : 204)
.frame(maxWidth: .infinity)
.background(.gray)
.padding()
}
}