I will provide simplified case.
I change my Text
font size during a transition by .matchedGeometryEffect
. I animate the text resizing with .onAppear
modifiers and it works fine. However, during the animation, as the text moves to its new position, text animation is not same as its frame animation, the text appears to be out of its boundaries, not animating in tandem with its frame, even though I apply same default animations everywhere.
struct SwiftUIView: View {
@Namespace var namespace
@State var move = false
@State var font: CGFloat = 15
var body: some View {
VStack {
Button("Move") {
withAnimation {
move.toggle()
}
}
if !move {
Text("Some Text")
.font(.system(size: font))
.padding()
.background(
RoundedRectangle(cornerRadius: 25)
.foregroundStyle(.blue)
)
.matchedGeometryEffect(id: "title", in: namespace)
.transition(.scale(scale: 1)) // Stops a fading out bug
.frame(width: 120)
.onAppear {
withAnimation {
font = 15
}
}
}
else {
Text("Some Text")
.font(.system(size: font))
.padding()
.background(
RoundedRectangle(cornerRadius: 25)
.foregroundStyle(.blue))
.matchedGeometryEffect(id: "title", in: namespace)
.transition(.scale(scale: 1)) // Stops a fading out bug
.offset(x: 50, y: 200)
.frame(width: 120)
.onAppear {
withAnimation {
font = 20
}
}
}
}
}
}
#Preview {
SwiftUIView()
}
The issue does not occur if I do not use .matchedGeometryEffect
(not switching views) or if I don't resize the text during the transition. I tried this approach using an animatable modifier which animates fine, but text reorganisation (if the number of text lines changes) doesn't animate during transition, and there is an issue if the animation is reversed before completion.
Is there a way to achieve the desired effect with .matchedGeometryEffect
, where the text's animation is in tandem with its frame animation? Any guidance or hints are highly appreciated.
UPD when I test on physical device (iPhone XS Max) and press "Move", Text
increases font and doesn't even move to new location until animation finishes, while blue rectangle does move. The reverse animation (after pressing the button again) works fine: