The matched geometry effect works properly when my code looks like this:
@State var isZoomed: Bool = false
@State var showText: Bool = false
@Namespace var namespace
var user: UserModel = exampleUsers[0]
var body: some View {
VStack {
if !isZoomed {
VStack {
Image(user.localProfileUrl!)
.resizable().aspectRatio(contentMode: .fit)
.matchedGeometryEffect(id: "rec", in: namespace)
.mask(RoundedRectangle(cornerRadius: 10)
.matchedGeometryEffect(id: "rec", in: namespace))
.frame(height: 100)
}
.overlay {
GeometryReader { geo in
VStack(alignment: .leading) {
Text(user.artistName!.uppercased())
.font(.title)
.bold()
.matchedGeometryEffect(id: "artistName", in: namespace)
Text(user.occupation)
.matchedGeometryEffect(id: "occupation", in: namespace)
Text("\(user.followers) Followers")
.matchedGeometryEffect(id: "followerCount", in: namespace) }
.frame(maxWidth: .infinity, maxHeight: 100, alignment: .bottomLeading)
.opacity(showText ? 1 : 0)
.padding()
}
}
.onTapGesture {
withAnimation() {
isZoomed.toggle()
showText.toggle()
}
}
}
if isZoomed {
VStack {
Image(user.localProfileUrl!)
.resizable().aspectRatio(contentMode: .fit)
.matchedGeometryEffect(id: "rec", in: namespace)
.mask(RoundedRectangle(cornerRadius: 20, style: .continuous)
.matchedGeometryEffect(id: "rec", in: namespace))
.frame(height: 500)
}
.overlay {
GeometryReader { geo in
VStack(alignment: .leading) {
Text(user.artistName!.uppercased())
.font(.title)
.bold()
.matchedGeometryEffect(id: "artistName", in: namespace)
Text(user.occupation)
.matchedGeometryEffect(id: "occupation", in: namespace)
Text("\(user.followers) Followers")
.matchedGeometryEffect(id: "followerCount", in: namespace)
}
.frame(maxWidth: .infinity, maxHeight: 500, alignment: .bottomLeading)
.opacity(showText ? 1 : 0)
.padding()
}
}
.onTapGesture {
withAnimation() {
isZoomed.toggle()
showText.toggle()
}
}
.offset(y: -100)
}
}
The effect smoothly transitions from a small frame to a large frame and back to a small frame (as intended). However, if I refactor the code to split the two views into separate vars like so:
var body: some View {
VStack {
if !isZoomed {
nonZoom
}
if isZoomed {
fullZoom
}
}
}
essentially putting the two Vstacks into separate vars, the geometry effect breaks:
So, why is such a simple tweak (which is quite a necessary one considering we need to separate views into files later on as the project gets more and more complicated) break the effect? And how do we fix it?