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()
}
}
目标:从 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()
}
}