如下面的代码所示,我的
CardContentView
由垂直排列在 VStack
中的元素组成。然而,当我将它放置在覆盖层中时,它的行为就好像它位于 ZStack
中一样。为什么会这样?
import SwiftUI
struct TestView: View {
@Namespace var namespace
@State var isShowDetail = false
@State var selectedCardIndex: Int?
var body: some View {
VStack {
Rectangle()
.fill(.gray.opacity(0.05))
.ignoresSafeArea()
}
.overlay {
if let selectedCardIndex, isShowDetail {
DetailView(selectedCardIndex)
.transition(.asymmetric(insertion: .identity, removal: .offset(y: 5)))
}
}
.overlay {
CardContentView()
}
}
@ViewBuilder
func TesttView(_ index: Int) -> some View {
Rectangle()
.frame(width: .infinity, height: 100)
.foregroundColor(.red.opacity(0.3))
.overlay {
Text("\(index)")
}
}
@ViewBuilder
func DetailView(_ index: Int) -> some View {
VStack {
TesttView(index)
.matchedGeometryEffect(id: index, in: namespace)
}
}
@ViewBuilder
func CardContentView() -> some View {
VStack {
ScrollView(.vertical, showsIndicators: false) {
ForEach(0..<10) { index in
VStack {
if index == selectedCardIndex && isShowDetail {
Rectangle()
.fill(.clear)
} else {
TesttView(index)
.matchedGeometryEffect(id: index, in: namespace)
.offset(y: isShowDetail ? 1000 : 0)
.rotation3DEffect(
.init(degrees: 10),
axis: (x: 1.0, y: 0.0, z: 0.0),
anchor: .center,
anchorZ: 0.0,
perspective: 1.0
)
.onTapGesture {
selectedCardIndex = index
withAnimation(.easeInOut(duration: 5)) {
isShowDetail.toggle()
}
}
.padding()
}
}
}
}
}
.overlay {
if let selectedCardIndex, isShowDetail {
VStack {
HStack {
Image(systemName: "chevron.left")
.onTapGesture {
withAnimation {
isShowDetail.toggle()
}
}
Spacer()
Text("Detail")
.font(.system(size: 20, weight: .bold))
}
DetailView(selectedCardIndex)
Spacer()
}
}
}
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
当我从覆盖层中删除 CardContentView 并将其放入 VStack 中时,它恢复正常。
var body: some View {
VStack {
CardContentView()
}
.overlay {
if let selectedCardIndex, isShowDetail {
DetailView(selectedCardIndex)
.transition(.asymmetric(insertion: .identity, removal: .offset(y: 5)))
}
}
.overlay {
// CardContentView()
}
}
由于 SwiftUI 处理视图布局和分层的方式,当放置在覆盖层中时,您的
CardContentView
的行为就像在 ZStack
中一样。
当您使用覆盖修改器时,它会将内容覆盖在基本视图的顶部。但是,在您的情况下,您在
VStack
内将多个视图叠加在一起。 SwiftUI 在内部使用 ZStack
来处理视图的叠加。这就是为什么您观察到类似于 ZStack
的行为。
当您从覆盖层中删除
CardContentView
并将其放入 VStack 中时,视图会按预期依次排列,因为 VStack
垂直堆叠视图。