我想将默认过渡(AnyTransition.opacity
)替换为另一个应用了matchedGeometryEffect()
修改器的视图过渡。我尝试了几种不同的技术,但似乎没有一种能做到这一点。
首先,这是matchedGeometryEffect
本身。ItemView
使用默认动画从一个容器“移动”到另一个容器。
struct ContentView: View {
@Namespace private var itemMovement
@State private var isInFirst = true
var body: some View {
VStack {
Text("First Container")
HStack {
if isInFirst {
ItemView()
.matchedGeometryEffect(id: "item", in: itemMovement)
}
}
.padding()
.border(.red)
Text("Second Container")
HStack {
if !isInFirst {
ItemView()
.matchedGeometryEffect(id: "item", in: itemMovement)
}
}
.padding()
.border(.red)
Button("Move Item") {
withAnimation {
isInFirst.toggle()
}
}
}
}
}
struct ItemView: View {
var body: some View {
Circle()
.foregroundStyle(.blue)
.frame(width: 100, height: 100)
}
}
字符串
x1c 0d1x的数据
仔细观察圆,可以看到动画中间的颜色变浅。我相信这是默认转换AnyTransition.opacity
的效果。为了删除该转换,我尝试在Circle视图中显式添加AnyTransition.identity
。
struct ContentView: View {
@Namespace private var itemMovement
@State private var isInFirst = true
var body: some View {
VStack {
Text("First Container")
HStack {
if isInFirst {
ItemView()
.transition(.identity) // <-- here
.matchedGeometryEffect(id: "item", in: itemMovement)
}
}
.padding()
.border(.red)
Text("Second Container")
HStack {
if !isInFirst {
ItemView()
.transition(.identity) // <-- here
.matchedGeometryEffect(id: "item", in: itemMovement)
}
}
.padding()
.border(.red)
Button("Move Item") {
withAnimation {
isInFirst.toggle()
}
}
}
}
}
型
然而,结果似乎是圆视图不再使用matchedGeometryEffect
动画。我已经尝试了一些变化,例如将.transition()
修改器放置在.matchedGeometryEffect()
修改器之后,并且一次仅在一个视图上使用.transition()
修改器-希望了解为什么会发生这种跳转到最终位置并制定新的解决方案。我还没想好
谁能帮我弄清楚如何将过渡与匹配的几何效果结合起来?除了这个简化的例子,我希望创建一个自定义的过渡,基于一个可动画化的视图修改器,它在内部将一个.rotation3DEffect()
应用到视图。
的
1条答案
按热度按时间relj7zay1#
这个例子似乎显示了一个圆圈从一个容器“移动”到另一个容器。实际上,它显示了两个圆,其中
matchedGeometryEffect
用于协调位置并平滑过渡。你观察到一个小的颜色变化的原因是因为第一个圆圈在第二个圆圈淡入的同时淡出。如果你仔细观察,HStacks的红色边框和第二个容器的标签也可以在圆形形状下看到,因为两个圆形在中间点都是不透明的。matchedGeometryEffect
的documentation声明,如果“isSource = true的组中当前插入的视图的数量不正好是一个”,则结果未定义。所以如果你真的想使用matchedGeometryEffect
,我建议你在第一种情况下添加isSource: isInFirst
,在第二种情况下添加isSource: !isInFirst
。然而,即使您通过使用.scale
转换(如前面的评论中所解释的)解决了淡入淡出问题,在实现您在问题中描述的.rotation3DEffect
时,您可能仍然会遇到困难。这是因为如果在两个单独的视图之间转换,效果将不会设置动画。因此,除了使用
matchedGeometryEffect
,另一种实现动画的方法是将位置的变化应用于单个圆。大概是这样的:字符串
注意事项:
matchedGeometryEffect
根本不需要rotation3DEffect
(正如你所描述的),这也会被平滑地动画化。ZStack
中的层)matchedGeometryEffect
控制其位置这样,您也应该能够设置旋转效果的动画。这里它是工作:
型