我有一个非常简单的场景,一个带有缩略图( ForEach of缩略图,ElementView)的列表,如果您单击其中一个,它将作为一个全屏详细信息视图(DetailView)打开。我想为此使用matchedGeometryEffect,以实现英雄动画。它几乎运行良好,但动画仍然不完美,看起来如果两个视图是分开处理的。
CollectionView.swift
struct CollectionView: View {
var data = [
"Test card 1",
"Test card 2",
"Test card 3",
"Test card 4",
"Test card 5"
]
@State var selectedElement: String?
@Namespace var namespace
var body: some View {
VStack {
if selectedElement == nil {
ScrollView {
LazyVGrid(columns: [GridItem(), GridItem()]){
ForEach(data.indices, id: \.self) { idx in
ElementView(text: data[idx])
.matchedGeometryEffect(id: idx, in: namespace, properties: .position)
.transition(.scale)
.onTapGesture {
withAnimation {
selectedElement = data[idx]
}
}
}
}
}
} else {
ForEach(data.indices, id: \.self) { idx in
if data[idx] == selectedElement {
DetailView(
text: selectedElement!,
backDidTap: {
withAnimation { selectedElement = nil }
}
)
.matchedGeometryEffect(id: idx, in: namespace, properties: .position)
.transition(.scale)
}
}
}
}
}
}
ElementView.swift
struct ElementView: View {
let text: String
var body: some View {
LazyVStack(spacing: .zero) {
Color.black
.frame(width: UIScreen.main.bounds.width / 2, height: UIScreen.main.bounds.width / 2)
Text(text)
.padding(.top, 8)
.frame(width: UIScreen.main.bounds.width / 2)
}
}
}
DetailView.swift
struct DetailView: View {
let text: String
let backDidTap: () -> Void
var body: some View {
VStack(alignment: .leading, spacing: .zero) {
Color.black
.edgesIgnoringSafeArea(.all)
.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height / 2)
.onTapGesture {
backDidTap()
}
Text(text)
.padding(.top, 8)
.padding(.leading, 8)
Spacer()
}
}
}
在模拟器上启用“慢动画”的结果:https://i.imgur.com/hW4qR6t.mp4
我认为这种转变有些不对劲,但我想不出是什么。我已经尝试过this了,因为问题非常相似,但是这种自定义转换对我不起作用。
发布于 2022-06-14 06:13:21
也许你已经找到了答案,但以下是我的解决方案:
问题是,在根视图中删除原始视图的条件是if。,因此swiftUI现在不再是视图动画的原始状态。这是我的解决方案:
struct CollectionView: View {
var data = [
"Test card 1",
"Test card 2",
"Test card 3",
"Test card 4",
"Test card 5"
]
@State var selectedElement: String?
@Namespace var namespace
var body: some View {
ZStack {
ScrollView {
LazyVGrid(columns: [GridItem(), GridItem()]){
ForEach(data.indices, id: \.self) { idx in
ElementView(text: data[idx])
.matchedGeometryEffect(id: data[idx], in: namespace, properties: .position)
//.transition(.scale)
.onTapGesture {
withAnimation {
selectedElement = data[idx]
}
}
}
}
}
.zIndex(1)
if let selected = selectedElement {
DetailView(text: selected, backDidTap: {
withAnimation { selectedElement = nil }
})
.matchedGeometryEffect(id: selected, in: namespace)
//.transition(.scale)
.zIndex(2)
}
}
}
}
https://stackoverflow.com/questions/70490144
复制相似问题