Home > Enterprise >  SwiftUI: Matched Geometry Effect doesn't work
SwiftUI: Matched Geometry Effect doesn't work

Time:03-29

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

  • Related