SwiftUI 中一个令人费解的现象:

问题描述 投票:0回答:1

如下面的代码所示,我的

CardContentView
由垂直排列在
VStack
中的元素组成。然而,当我将它放置在覆盖层中时,它的行为就好像它位于
ZStack
中一样。为什么会这样?

Screenshot

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

Screenshot

swiftui overlay
1个回答
0
投票

由于 SwiftUI 处理视图布局和分层的方式,当放置在覆盖层中时,您的

CardContentView
的行为就像在
ZStack
中一样。

当您使用覆盖修改器时,它会将内容覆盖在基本视图的顶部。但是,在您的情况下,您在

VStack
内将多个视图叠加在一起。 SwiftUI 在内部使用
ZStack
来处理视图的叠加。这就是为什么您观察到类似于
ZStack
的行为。

当您从覆盖层中删除

CardContentView
并将其放入 VStack 中时,视图会按预期依次排列,因为
VStack
垂直堆叠视图。

© www.soinside.com 2019 - 2024. All rights reserved.