当我使用匹配的几何视图修改器时,我总是收到警告
Multiple inserted views in matched geometry group Pair<String, ID>(first: "id1", second: SwiftUI.Namespace.ID(id: 8)) have isSource: true, results are undefined.
虽然动画静止图像仍然有效,但我想了解为什么收到此警告以及如何解决该问题。
这是我制作的动画,有什么想法摆脱警告吗?
使用以下代码
struct ContentView: View {
@State var details = false
@Namespace var animation
var body: some View {
ZStack {
HStack {
Rectangle()
.frame(width: 100, height: 100)
.matchedGeometryEffect(id: "id1", in: animation)
.onTapGesture {
withAnimation {
details.toggle()
}
}
Spacer()
}
.zIndex(1)
if details == true {
AnotherView(details: $details, animation: animation)
.zIndex(2)
}
}
}
}
struct AnotherView: View {
@Binding var details: Bool
var animation: Namespace.ID
var body: some View {
ZStack {
Color.red
Rectangle()
.frame(width: 300, height: 300)
.matchedGeometryEffect(id: "id1", in: animation)
.onTapGesture {
withAnimation {
details.toggle()
}
}
}
}
}
答案 0 :(得分:3)
问题是您同时在屏幕上拥有两个视图(即使第二个视图覆盖了第一个视图,第一个视图仍然存在)。使用.matchedGeometryEffect
时,一个视图在逻辑上将替换另一个视图,因此在绘制第二个视图时需要删除第一个视图。您可以通过仅在Rectangle
时绘制第一个!details
来解决此问题。
此外,我将.matchedGeometryEffect
移为Rectangle
的第一个修饰符,以产生更清晰的效果。
struct ContentView: View {
@State var details = false
@Namespace var animation
var body: some View {
ZStack {
HStack {
if !details {
Rectangle()
.matchedGeometryEffect(id: "id1", in: animation)
.frame(width: 100, height: 100)
.onTapGesture {
withAnimation {
details.toggle()
}
}
}
Spacer()
}
.zIndex(1)
if details {
AnotherView(details: $details, animation: animation)
.zIndex(2)
}
}
}
}
struct AnotherView: View {
@Binding var details: Bool
var animation: Namespace.ID
var body: some View {
ZStack {
Color.red
Rectangle()
.matchedGeometryEffect(id: "id1", in: animation)
.frame(width: 300, height: 300)
.onTapGesture {
withAnimation {
details.toggle()
}
}
}
}
}
.matchedGeometryEffect
Documentation的状态(添加了bold):
如果在同一事务中插入一个视图,并且删除了另一个具有相同键的视图,则系统将在窗口空间中插入其框架矩形,以使似乎有一个视图从其旧位置移至。通常的过渡机制定义了过渡期间如何渲染两个视图中的每个视图(例如淡入/淡出,缩放等),matchedGeometryEffect()修饰符仅将视图的几何布置为被链接,而不是它们的呈现。
如果isSource = true的组中当前插入的视图数不完全是一个未定义的结果,因为不清楚哪个是源视图。
答案 1 :(得分:0)
以下变体在Preview中也适用(以防万一,@ vacawama提出的建议不适用于Preview)。
通过Xcode 12.0 / iOS 14测试
struct ContentView: View {
@State var details = false
@Namespace var animation
var body: some View {
ZStack {
HStack {
if !details {
Rectangle()
.matchedGeometryEffect(id: "id1", in: animation)
.frame(width: 100, height: 100)
.onTapGesture {
details.toggle()
}
}
Spacer()
}.animation(.default, value: details)
if details {
AnotherView(details: $details, animation: animation)
}
}.animation(.default, value: details)
}
}
struct AnotherView: View {
@Binding var details: Bool
var animation: Namespace.ID
var body: some View {
ZStack {
Color.red
Rectangle()
.matchedGeometryEffect(id: "id1", in: animation)
.frame(width: 300, height: 300)
.onTapGesture {
details.toggle()
}
}
}
}