title: SwiftUI: presenting modal view with custom transition from frame to frame?
body: <p>I am trying to replicate what I used to do in UIKit when presenting a ViewController using <code>UIViewControllerTransitioningDelegate</code> and <code>UIViewControllerAnimatedTransitioning</code>.</p>
  <p>So, for example, from a view that looks like this:</p>
  <p><a href="https://i.stack.imgur.com/DSDya.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/DSDya.png" alt="enter image description here" /></a></p>
  <p>I want to present a view (I would say a modal view but I am not sure if that is the correct way to go about it in SwiftUI) that grows from the view A into this:</p>
  <p><a href="https://i.stack.imgur.com/IHaWO.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/IHaWO.png" alt="enter image description here" /></a></p>
  <p>So, I need view B to fade in growing from a frame matching view A into almost full screen. The idea is the user taps on A as if it wanted to expand it into its details (view B).</p>
  <p>I looked into SwiftUI transitions, things like this:</p>
  <pre><code>extension AnyTransition {
      static var moveAndFade: AnyTransition {
          let insertion = AnyTransition.move(edge: .trailing)
              .combined(with: .opacity)
          let removal = AnyTransition.scale
              .combined(with: .opacity)
          return .asymmetric(insertion: insertion, removal: removal)
      }
  }
  </code></pre>
  <p>So, I think I need to build a custom transition. But, I am not sure how to go about it yet being new to this.</p>
  <p>How would I build a transition to handle the case as described? Being able to have a <code>from frame</code> and a <code>to frame</code>...?</p>
  <p>Is this the right way of thinking about it in SwiftUI?</p>
  <p>New information:</p>
  <p>I have tested <code>matchedGeometryEffect</code>.</p>
  <p>Example:</p>
  <pre><code>struct TestParentView: View {
      
      
      @State private var expand = false
      @Namespace private var shapeTransition
      
      var body: some View {
  
          VStack {
              if expand {
           
                  // Rounded Rectangle
                  Spacer()
           
                  RoundedRectangle(cornerRadius: 50.0)
                      .matchedGeometryEffect(id: &quot;circle&quot;, in: shapeTransition)
                      .frame(minWidth: 0, maxWidth: .infinity, maxHeight: 300)
                      .padding()
                      .foregroundColor(Color(.systemGreen))
                      .animation(.easeIn)
                      .onTapGesture {
                          expand.toggle()
                      }
           
              } else {
           
                  // Circle
                  RoundedRectangle(cornerRadius: 50.0)
                      .matchedGeometryEffect(id: &quot;circle&quot;, in: shapeTransition)
                      .frame(width: 100, height: 100)
                      .foregroundColor(Color(.systemOrange))
                      .animation(.easeIn)
                      .onTapGesture {
                          expand.toggle()
                      }
           
                  Spacer()
              }
          }
      }
  
  }
  </code></pre>
  <p>It looks like <code>matchedGeometryEffect</code> could be the tool for the job.
  However, even when using <code>matchedGeometryEffect</code>, I still can't solve these two things:</p>
  <ol>
  <li>how do I include a fade in / fade out animation?</li>
  <li>looking at the behavior of <code>matchedGeometryEffect</code>, when I &quot;close&quot; view B, view B disappears immediately and what we see animating is view A from where B was back to view A's original frame. I actually want view B to scale down to where A is as it fades out.</li>
  </ol>