【发布时间】:2021-12-08 21:14:14
【问题描述】:
考虑以下示例:
struct ContentView: View {
@State var showSplash: Bool = true
@Namespace var animationNamespace
var body: some View {
ZStack {
if showSplash {
GeometryReader { geometry in
AsyncImage(url: URL(string: "https://picsum.photos/seed/864a5875-6d8b-43d6-8d65-04c5cfb13f3b/1920/1440")) { image in
image.resizable()
.scaledToFill()
.matchedGeometryEffect(id: "SplashImage", in: animationNamespace)
.transition(.move(edge: .bottom))
.frame(width: geometry.size.width)
.transition(.move(edge: .bottom))
.edgesIgnoringSafeArea(.all)
.clipped()
} placeholder: {
Color.gray
}
}
.onTapGesture {
toggleSplashScreen(false)
}
} else {
ScrollView {
GeometryReader { geometry in
AsyncImage(url: URL(string: "https://picsum.photos/seed/864a5875-6d8b-43d6-8d65-04c5cfb13f3b/1920/1440")) { image in
image
image
.resizable()
.scaledToFill()
.matchedGeometryEffect(id: "SplashImage", in: animationNamespace)
.transition(.move(edge: .bottom))
} placeholder: {
Color.gray
}
.frame(width: geometry.size.width, height: 400)
.clipped()
}
.edgesIgnoringSafeArea(.all)
.onTapGesture {
toggleSplashScreen(true)
}
}
}
}
}
}
这里有一个辅助方法:
private extension ContentView {
func toggleSplashScreen(_ toggle: Bool) {
withAnimation(.spring(response: 0.85, dampingFraction: 0.95)) {
showSplash = toggle
}
}
}
这会产生:
我注意到这里有两件事我想解决
- 在两种状态之间转换时闪烁的白色效果。
- 我注意到,由于我们使用的是
AsyncImage,当showSplash更改时,AsyncImages 有时只会碰到placeholder块。结果,过渡变得非常不稳定。我使用资产文件中的静态图像对此进行了测试,然后过渡变得平滑。我还尝试在 AsyncImage 上创建缓存机制,但有时会遇到placeholder块的问题。
很想听听任何想法 :) 谢谢!
【问题讨论】:
-
MatchedGeometry效果比您所拥有的要复杂一些。 SwiftUI Lab 有很多关于这个和高级动画的帖子。我认为您遇到的问题是您没有向MatchedGeometry提供在两个视图之间无缝转换所需的信息,因此您得到了您所看到的行为。MatchedGeometry需要一种方法来计算转换之间的样子,而这在您的代码中不存在。
标签: ios swiftui ios15 swiftui-geometryeffect swiftui-asyncimage