swift matchedGeometryEffect在目标位于菜单标签内时行为异常

hc8w905p  于 2023-08-02  发布在  Swift
关注(0)|答案(1)|浏览(77)

我正在用一些动画来美化SwiftUI应用程序。一个地方,将是很好的动画是一个图像的位置在卡片转换状态和图像成为互动。
问题是这个图像变成了一个Menu,这引入了一个奇怪的动画效果。这是它在示例项目中的样子:x1c 0d1x的数据
值得注意的是,它在取消选择时正确地动画-图像会移动,而不是从底部出现。
我知道问题出在Menu上,因为如果我把菜单标签拉出来,动画就能正常工作:


下面是演示问题的简单示例代码:

import SwiftUI

struct ContentView: View {
    @State var selected = false
    @Namespace var animation
    
    var body: some View {
        VStack {
            Text(selected ? "Selected card" : "Deselected card").font(.title).padding(20)
            if selected {
                HStack {
                    Button(action: {}, label: {
                        Image(systemName: "trash")
                    })
                    Spacer()
                    Menu(content: {
                        Button("Order Now", action: {})
                        Button("Adjust Order", action: {})
                    }, label: {

                        Image(systemName: "paperplane")
                            .matchedGeometryEffect(id: "send", in: animation)
                       
                    })
                }
                .padding(20)
            } else {
                HStack {
                    Text("Timestamp")
                    Spacer()
                        Image(systemName: "paperplane")
                            .matchedGeometryEffect(id: "send", in: animation)

                }
            }
        }
        .foregroundColor(.white)
        .padding(20)
        .background(.blue)
        .clipShape(RoundedRectangle(cornerRadius: 24))
        .onTapGesture {
            withAnimation {
                selected.toggle()
            }
        }
        .padding(20)
    }
}

字符串
要“修复”它,只需将Image从菜单标签中移出,并查看其动画是否正确。
我尝试了几种解决方法来解决此问题:
1.将Menu.disabled一起使用Menu,然后将matchedGeometryEffect移动到菜单本身。这 * 工作 *,但不是我想要的,因为在我的实际用例中,菜单是一个HStack的图像和一个文本标签,而text labels do not behave nicely with matchedGeometryEffect
1.使用.overlay和/或ZStack隐藏图像下方的菜单。这也可以正常工作,但意味着当点击菜单图像时,图像不会像正常情况那样变灰。
1.我已经研究了使图像只是一个按钮,并创建菜单而不使用Menu。这看起来很恶心。
任何关于如何最好地接近这一点的想法将不胜感激!

dfuffjeb

dfuffjeb1#

我建议在这里避免使用MatchedGeometryEffect,并将selected的使用移到HStack内部。在Menu上使用.disabled(selected),启用/禁用其作为Menu的使用。由于不再使用MatchedGeometryEffect,使用带有Menu标题的文本不再是问题。

struct ContentView: View {
    @State var selected = false
    @Namespace var animation
    
    var body: some View {
        VStack {
            ZStack {
                Text("Selected card").opacity(selected ? 1 : 0)
                Text("Deselected card").opacity(selected ? 0 : 1)
            }.font(.title).padding(20)
            HStack {
                if selected {
                    Button(action: {}, label: {
                        Image(systemName: "trash")
                    })
                } else {
                    Text("Timestamp")
                }
                Spacer()
                Menu(content: {
                    Button("Order Now", action: {})
                    Button("Adjust Order", action: {})
                }, label: {
                    HStack {
                        Image(systemName: "paperplane")
                        ZStack(alignment: .leading) {
                            Text("Not").opacity(selected ? 1 : 0)
                            Text("Menu").opacity(selected ? 0 : 1)
                        }
                    }
                    
                }).disabled(selected)
            }
            .padding(selected ? 20 : 0)
            
        }
        .foregroundColor(.white)
        .padding(20)
        .background(.blue)
        .clipShape(RoundedRectangle(cornerRadius: 24))
        .onTapGesture {
            withAnimation {
                selected.toggle()
            }
        }
        .padding(20)
    }
}

字符串
x1c 0d1x的数据

相关问题