问题描述
目标:从列表传递图像数据 -> 细节与缩放动画类似于 Apple 照片应用。
问题:我只能让它硬编码工作,因为我在同一个 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
属性包装器在视图之间传递数据。
为此,您需要具有已发布属性的可观察对象类(例如 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()
}
}