I have not played with matchedGeometryEffect yet, so read the followings as as far as I tried things. There may be other better ways.
Text, is duplicated during the transition
You have two Texts, and with using matchedGeometryEffect, they both are animated.
Applying matchedGeometryEffect after frame is specified, the positions of the two in animation are different.
Please try moving matchedGeometryEffect before frame.
when I press again to get it back to its original position, no animation takes place
Seems some sort of symmetry is needed to trigger animation when you set numberViewModel.tapped to false.
Please try something like this:
struct NumberView: View {
@ObservedObject var numberViewModel: NumberViewModel
var animation: Namespace.ID
var number: Number
var body: some View{
GroupBox{
if numberViewModel.selected.number != number.number {
Text("\(number.number)")
.font(.largeTitle)
.matchedGeometryEffect(id: number.number, in: animation) //<-
.frame(width: 100, height: 100, alignment: .center)
}
}
}
}
struct NumberTappedView: View {
var animation: Namespace.ID
@ObservedObject var numberViewModel: NumberViewModel
var body: some View{
GroupBox {
if numberViewModel.tapped { //<-
Text("\(numberViewModel.selected.number)")
.font(.largeTitle)
.matchedGeometryEffect(id: numberViewModel.selected.number, in: animation) //<-
.frame(width: 200, height: 200, alignment: .center)
} //<-
}
}
}
Or you would prefer this version of NumberTappedView:
struct NumberTappedView3: View {
var animation: Namespace.ID
@ObservedObject var numberViewModel: NumberViewModel
var body: some View{
GroupBox {
if numberViewModel.tapped {
ZStack {
ForEach(numbers) { number in
if numberViewModel.selected.number == number.number {
Text("\(numberViewModel.selected.number)")
.font(.largeTitle)
.matchedGeometryEffect(id: numberViewModel.selected.number, in: animation)
.frame(width: 200, height: 200, alignment: .center)
}
}
}
}
}
}
}