在 SwiftUI 中,我在 ZStack 中创建了 2x2 颜色网格。我想单击一种颜色,并在我的 ZStack 中使用 .matchedGeometryEffect 将其扩展为 DetailView,而不具有任何透明度。使用以下代码很容易做到这一点:
import SwiftUI
struct ContentView: View {
let colors: [Color] = [.red, .orange, .green, .indigo]
@Namespace var nameSpace
@State var showDetailView = false
@State var selectedColorIndex: Int? = nil
var body: some View {
ZStack {
Color.blue
Grid(horizontalSpacing: 0, verticalSpacing: 0) {
ForEach(0..<2) { row in
GridRow {
ForEach(0..<2) { column in
let index = (row * 2) + column
colors[index]
.matchedGeometryEffect(id: index, in: nameSpace)
.onTapGesture {
withAnimation {
selectedColorIndex = index
showDetailView = true
}
}
.zIndex(selectedColorIndex == index ? 1 : 0)
}
}
}
}
if showDetailView {
if let index = selectedColorIndex {
colors[index]
.matchedGeometryEffect(id: index, in: nameSpace)
.onTapGesture {
withAnimation {
showDetailView = false
}
}
.zIndex(1)
}
}
}
.frame(width: 300, height: 300)
}
}
但是,这会出现以下错误。
匹配几何组 Pair 中的多个插入视图
(第一个:1,第二个:SwiftUI.Namespace.ID(id:86))有 ,结果未定义。isSource: true
我了解此错误背后的原因。当呈现较大的细节视图时,我仍然呈现较小的视图。使用逻辑(if 语句)有条件地删除特定的较小视图,从而消除错误消息非常容易。然而,它破坏了我的 ZIndex,并且我尝试过的任何方法都无法让我找到维护我的属性 ZIndex 布局的解决方案。
这是我尝试过的众多事情之一。它消除了错误,但破坏了颜色扩展到其他颜色的效果。
ZStack {
Color.blue
Grid(horizontalSpacing: 0, verticalSpacing: 0) {
ForEach(0..<2) { row in
GridRow {
ForEach(0..<2) { column in
let index = (row * 2) + column
if index != selectedColorIndex {
colors[index]
.matchedGeometryEffect(id: index, in: nameSpace)
.onTapGesture {
withAnimation {
selectedColorIndex = index
showDetailView = true
}
}
.zIndex(selectedColorIndex == index ? 1 : 0)
} else { Color.clear}
}
}
}
}
if showDetailView {
if let index = selectedColorIndex {
colors[index]
.matchedGeometryEffect(id: index, in: nameSpace)
.onTapGesture {
withAnimation {
showDetailView = false
selectedColorIndex = nil
}
}
.zIndex(1)
}
}
}
.frame(width: 300, height: 300)
我也尝试了很多方法,我发现这很有效。
将您的第一个
.matchedGeometryEffect
更改为:
.matchedGeometryEffect(id: index, in: nameSpace)
至:
.matchedGeometryEffect(id: index, in: nameSpace, isSource: !showDetailView)
这可确保始终只有一个
isSource == true
有效。
然后添加:
.transition(.scale(scale: 0.000001))
到您的详细视图以替换默认的淡入过渡。
这是全部代码:
struct ContentView: View {
let colors: [Color] = [.red, .orange, .green, .indigo]
@Namespace var nameSpace
@State var showDetailView = false
@State var selectedColorIndex: Int? = nil
var body: some View {
ZStack {
Color.blue
Grid(horizontalSpacing: 0, verticalSpacing: 0) {
ForEach(0..<2) { row in
GridRow {
ForEach(0..<2) { column in
let index = (row * 2) + column
colors[index]
.matchedGeometryEffect(id: index, in: nameSpace, isSource: !showDetailView)
.onTapGesture {
withAnimation {
selectedColorIndex = index
showDetailView = true
}
}
.zIndex(selectedColorIndex == index ? 1 : 0)
}
}
}
}
if showDetailView {
if let index = selectedColorIndex {
colors[index]
.matchedGeometryEffect(id: index, in: nameSpace)
.transition(.scale(scale: 0.000001))
.onTapGesture {
withAnimation {
showDetailView = false
}
}
.zIndex(1)
}
}
}
.frame(width: 300, height: 300)
}
}