In SwiftUI, I’m working with two screens, Screen A and Screen B. I’m attempting to create a transition effect using SwiftUI’s matched geometry feature. The transition involves two rounded rectangles: one on Screen A, which appears as a circle due to its corner radius and size, and another on Screen B with a zero corner radius, serving as the background.
Expected Behavior:
I anticipated the animation would display as a seamless morphing of a single object from one configuration to another, specifically altering the corner radius, height, and width.
Actual Behavior:
However, the transition seems to be more of a crossfade. The source shape animates its corner radius towards the target configuration, but the target shape, fading in with a static zero corner radius, doesn’t animate from the source radius.
Minimal Example Code:
Main Screen:
enum Screen {
case main, target
}
@Observable
class Nav {
var screen:Screen = .main
}
struct ContentView: View {
@Environment(Nav.self) var navController
// matched geometry
@Namespace var namespace
var body: some View {
switch navController.screen {
case .main:
ZStack{
RoundedRectangle(cornerRadius: 15)
.fill(Color.green)
.matchedGeometryEffect(id: "circleToBackground", in: namespace)
.frame(width: 30, height: 30)
.onTapGesture {
withAnimation(.easeInOut(duration: 4.0)){
navController.screen = .target
}
}
}
case .target:
TargetScreen(namespace: namespace)
}
}
}
Target Screen:
struct TargetScreen: View {
let namespace: Namespace.ID
@Environment(Nav.self) var navController
var body: some View {
ZStack {
RoundedRectangle(cornerRadius: 0)
.fill(LinearGradient(colors: [Color.green, Color.white], startPoint: UnitPoint(x:0.5,y:0.0), endPoint: UnitPoint(x:0.5,y:1.0)))
.matchedGeometryEffect(id: "circleToBackground", in: namespace)
.frame(maxWidth: .infinity, maxHeight: .infinity)
Text("BACK").onTapGesture {
withAnimation {
navController.screen = .main
}
}
}
}
}