SwiftUI - 传递图像数据 f List -> 使用 matchedGeometryEffect 缩放动画的细节

SwiftUI -pass image data f List -> Detail with scaling animation using matchedGeometryEffect

目标:从 List -> Detail 传递图像数据,并在类似于 Apple Photos App 的动画中进行缩放缩放。

我所做的:使用匹配的几何效果,效果非常好。

问题:我只能通过硬编码让它工作,因为我在同一个 ContentView() 上同时拥有 List() 和 Detail(),我不知道如何传递数据 List-> Detail

感谢任何意见!

import SwiftUI




struct Grid: View {
    
    let namespace: Namespace.ID
    
    var body: some View {
        
        List{
           Image("cover")
                .resizable()
                .frame(width: 50, height: 50)
                .cornerRadius(4)
                .padding()
                .matchedGeometryEffect(id: "animation", in: namespace)
            
            Image("cover2")
                 .resizable()
                 .frame(width: 50, height: 50)
                 .cornerRadius(4)
                 .padding()
                 .matchedGeometryEffect(id: "animation", in: namespace)
        }

   }
}

struct Detail: View {
    
    let namespace: Namespace.ID
    
    var body: some View {
        
            Image("cover")
                .resizable()
                .aspectRatio(contentMode: .fit)
                .cornerRadius(10)
                .padding(40)
                .matchedGeometryEffect(id: "animation", in: namespace)
        
      
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color(#colorLiteral(red: 0.234857142, green: 0.043259345, blue: 0.04711621255, alpha: 1)))
    }
}

struct ContentView: View {
    
    @Namespace private var ns
    @State private var showDetails: Bool = false
    
    var body: some View {
        ZStack {
            Spacer()
            if showDetails {
                Detail(namespace: ns)
            }
            else {
                Grid(namespace: ns)
            }
        }
        .onTapGesture {
            withAnimation(.spring()) {
                showDetails.toggle()
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

您可以使用 @EnvironmentObject 属性 包装器在视图之间传递数据。 为此,您需要具有已发布属性的可观察对象 class(例如 CoverData)。

此外,对于要分组的视图(例如图像名称),您应该使用 matchedGeometryEffect 的唯一 ID

我对你的代码做了最小的改动,看看这是否是你要找的:

import SwiftUI


class CoverData: ObservableObject {
    @Published var images = ["cover", "cover2"]
    @Published var selected = ""
    @Published var showDetails: Bool = false
}

struct Grid: View {
    @EnvironmentObject var coverData: CoverData
    
    let namespace: Namespace.ID
    
    var body: some View {
        
        List {
            ForEach(coverData.images.indices) { index in
                let image = coverData.images[index]
                Image(image)
                    .resizable()
                    .frame(width: 50, height: 50)
                    .cornerRadius(4)
                    .padding()
                    .matchedGeometryEffect(id: image, in: namespace)
                    .onTapGesture {
                        coverData.selected = image
                        withAnimation(.spring()) {
                            coverData.showDetails.toggle()
                        }
                    }
            }
        }
   }
}

struct Detail: View {
    @EnvironmentObject var coverData: CoverData

    let namespace: Namespace.ID
    
    var body: some View {
        
            Image(coverData.selected)
                .resizable()
                .aspectRatio(contentMode: .fit)
                .cornerRadius(10)
                .padding(40)
                .matchedGeometryEffect(id: coverData.selected, in: namespace)
        
      
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color(#colorLiteral(red: 0.234857142, green: 0.043259345, blue: 0.04711621255, alpha: 1)))
    }
}

struct ContentView: View {
    
    @Namespace private var ns
    @StateObject private var coverData = CoverData()
    
    var body: some View {
        ZStack {
            Spacer()
            if coverData.showDetails {
                Detail(namespace: ns)
                .onTapGesture {
                    withAnimation(.spring()) {
                        coverData.showDetails.toggle()
                    }
                }
            }
            else {
                Grid(namespace: ns)
            }
        }
        .environmentObject(coverData)
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}