Here is a simple example code. When Button
is pushed, Image
appears to the left of the Text
, causing Text
to shrink.
But when animations happens, the letters of the Text
wobble in horizontal direction.
Here is a link to the animated example:
TextTruncatingTest.gif
import SwiftUI
struct TextTruncatingTest: View {
@State private var imageVisible: Bool = true
var body: some View {
VStack {
Button {
withAnimation {
imageVisible.toggle()
}
} label: {
Text("Toggle Image")
}
HStack {
if imageVisible {
Image(systemName: "circle")
}
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
.transition(.identity)
.lineLimit(1)
}
.padding()
.background {
RoundedRectangle(cornerRadius: 20, style: .continuous)
.foregroundStyle(Color.basicSecondaryBackground)
}
}
.padding()
}
}
#Preview {
TextTruncatingTest()
}
I tried to use .transition(.identity)
on Text
, it did not help. I need to preserve this type of layout and find the solution to this animation problem.
I couldn't see the problem when running on an iPhone 16 simulator with iOS 18. However, I was able to reproduce it by running on an iPhone 15 simulator with iOS 17.5.
The .transition
modifier is not doing anything, because the text view is not appearing or disappearing, it is just changing size. However, you could try replacing it with .contentTransition
instead. This is intended for when the text really changes (instead of just changing size) but it works to an extent for a change of size too.
I found that none of the available content transitions gave a very satisfactory animation either. But I found that adding .drawingGroup()
to the Text
makes it behave similarly to iOS 18:
Text("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.")
.lineLimit(1)
// .contentTransition(.identity)
.drawingGroup() // 👈 HERE
The Xcode project I tried this on actually had a build target of iOS 16. If you are targeting iOS 17 or above then you could try .geometryGroup()
instead. This might have fewer side effects than drawingGroup()
.