0

我正在实现自定义菜单视图,从顶部尾随位置过渡外观。我正在使用matchedGeometryEffect视图背景。问题在于第二视图的子视图。它们出现在动画结束之前。你可以在下面看到:

在此处输入图像描述

如何将这些按钮视图与父视图的动画同步?

在我的代码下面:

struct ContentView: View {
    @State var show = false
    @Namespace var namespace
    var body: some View {
        VStack(spacing: 0) {
            HStack(spacing: 0) {
                Spacer()
                Button(action: {
                    withAnimation(.linear(duration: 1.2)) { // Longer duration for demo of issue
                        show.toggle()
                    }
                }) {
                    Image(systemName: "ellipsis.circle")
                        .font(.title3)
                        .background( !show ?
                            Color.clear
                                .matchedGeometryEffect(id: "topMenuToggle", in: namespace, properties: .position)
                            : nil
                        )
                }
            }
            .padding()
            Color.clear
                .overlay(
                    show ? MenuView(namespace: namespace) : nil
                    , alignment: .topTrailing
                )
        }
        .foregroundColor(.white)
        .background(Color.black.ignoresSafeArea())
    }
}
struct MenuView: View {
    let namespace: Namespace.ID
    var body: some View {
        VStack(spacing: 0) {
            Button(action: {
                
            }) {
                HStack(spacing: 0) {
                    Text("Save video")
                        .font(.body)
                    Spacer(minLength: 0)
                    Image(systemName: "arrow.down.circle")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(height: 20)
                }
            }
            .padding(.top, 18)
            .padding(.bottom, 18)
            .padding(.horizontal, 14)
            Rectangle()
                .fill(Color.white.opacity(0.1))
                .frame(maxWidth: .infinity, maxHeight: 1)
            Button(action: {
                
            }) {
                HStack(spacing: 0) {
                    Text("Report")
                        .font(.body)
                    Spacer(minLength: 0)
                    Image(systemName: "exclamationmark.bubble")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(height: 20)
                }
            }
            .padding(.top, 16)
            .padding(.bottom, 18)
            .padding(.horizontal, 14)
        }
        .foregroundColor(.white)
        .frame(width: 250)
        .background(
            Color.white.opacity(0.2)
                .matchedGeometryEffect(id: "topMenuToggle", in: namespace, anchor: .bottomLeading)
        )
        .cornerRadius(12)
    }
}
4

1 回答 1

0

我能够通过MatchedGeometryEffect为每个行项目和源视图添加来修复动画。也许这不是正确的方法,但它以某种方式起作用。修改后的代码:

Button(action: {
    withAnimation(.easeInOut(duration: 1.2)) {
        show.toggle()
    }
}) {
    Image(systemName: "ellipsis.circle")
        .background( !show ?
            Color.clear
                .matchedGeometryEffect(id: "topMenuBg", in: namespace, properties: .position)
                .matchedGeometryEffect(id: "topMenuRow0", in: namespace, properties: .position)
                .matchedGeometryEffect(id: "topMenuRow1", in: namespace, properties: .position)
                .matchedGeometryEffect(id: "topMenuRow2", in: namespace, properties: .position)
            : nil
        )
}

MenuView.swift

VStack(spacing: 0) {
    Button(action: {}) {
        HStack(spacing: 0) {}
    }
    .matchedGeometryEffect(id: "topMenuRow0", in: namespace)
    Rectangle()
        .fill(Color.white.opacity(0.1))//
        .frame(maxWidth: .infinity, maxHeight: 1)
        // Before frame() the height is broken weirdly
        .matchedGeometryEffect(id: "topMenuRow1", in: namespace)
    Button(action: {}) {
        HStack(spacing: 0) {}
    }
    .matchedGeometryEffect(id: "topMenuRow2", in: namespace)
}
.frame(width: 250)
.background(
    Color.white.opacity(0.2)
        .matchedGeometryEffect(id: "topMenuBg", in: namespace, anchor: .bottomLeading)
)

演示:

在此处输入图像描述

于 2021-10-24T13:41:18.400 回答