I am making app which is using Matched Geometry Effect. It is matching two rectangles embedded inside two different views. It isn't working as it supposed to. Please help me. Here is test view for that:
struct ContentViewTest: View {
@State var details = false
@Namespace var animation
var body: some View {
ZStack {
if !details {
TestView2(details: $details, anim: animation)
}
if details {
TestView1(details: $details, anim: animation)
}
}
}
}
Here is TestView1:
struct TestView1: View {
@Binding var details: Bool
var anim: Namespace.ID
var body: some View {
ZStack{
Color.gray.ignoresSafeArea()
Color.red.frame(width: 300, height: 700)
.matchedGeometryEffect(id: "id1", in: anim)
.onTapGesture {
withAnimation {
details = false
}
}
}
}
}
And here is TestView2:
struct TestView2: View {
@Binding var details: Bool
var anim: Namespace.ID
var body: some View {
ZStack{
Color.green.ignoresSafeArea()
Color.red.frame(width: 200, height: 200)
.matchedGeometryEffect(id: "id1", in: anim)
.onTapGesture {
withAnimation {
details = true
}
}
}
}
}
CodePudding user response:
This an approach for your issue, using transition with along matchedGeometryEffect in correct place:
struct ContentView: View {
@State var details = false
@Namespace var namespace
private let id: String = "myID"
var body: some View {
if (details) {
TestView1(details: $details, id: id, namespace: namespace)
}
else {
TestView2(details: $details, id: id, namespace: namespace)
}
}
}
struct TestView1: View {
@Binding var details: Bool
let id: String
var namespace: Namespace.ID
var body: some View {
ZStack {
Color.gray.ignoresSafeArea()
Color.red
.matchedGeometryEffect(id: id, in: namespace)
.transition(.scale(scale: 1.0))
.frame(width: 300, height: 700)
.onTapGesture {
withAnimation {
details = false
}
}
}
}
}
struct TestView2: View {
@Binding var details: Bool
let id: String
var namespace: Namespace.ID
var body: some View {
ZStack {
Color.green.ignoresSafeArea()
Color.red
.matchedGeometryEffect(id: id, in: namespace)
.transition(.scale(scale: 1.0))
.frame(width: 200, height: 200)
.onTapGesture {
withAnimation {
details = true
}
}
}
}
}
CodePudding user response:
Just add properties
position (in both matched views), like in below
Color.red.frame(width: 300, height: 700)
.matchedGeometryEffect(id: "id1", in: anim, properties: .position) // << here !!
or (depending on effect which you want to achieve) change order of modifiers (for both views), like
Color.red
.matchedGeometryEffect(id: "id1", in: anim) // << here !!
.frame(width: 300, height: 700)
Tested with Xcode 13.2 / iOS 15.2