I am trying to replicate what I used to do in UIKit when presenting a ViewController using UIViewControllerTransitioningDelegate and UIViewControllerAnimatedTransitioning.
So, for example, from a view that looks like this:
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:
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).
I looked into SwiftUI transitions, things like this:
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)
}
}
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.
How would I build a transition to handle the case as described? Being able to have a from frame and a to frame...?
Is this the right way of thinking about it in SwiftUI?
New information:
I have tested matchedGeometryEffect.
Example:
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: "circle", 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: "circle", in: shapeTransition)
.frame(width: 100, height: 100)
.foregroundColor(Color(.systemOrange))
.animation(.easeIn)
.onTapGesture {
expand.toggle()
}
Spacer()
}
}
}
}
It looks like matchedGeometryEffect could be the tool for the job.
However, even when using matchedGeometryEffect, I still can't solve these two things:
- how do I include a fade in / fade out animation?
- looking at the behavior of
matchedGeometryEffect, when I "close" 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.


