animationswiftuitext

SwiftUI Text with truncation wobbles when animating view's width


Here is a simple example code. When Button is pushed, Image appears to the left of the Text, causing Text to shrink.

TextTruncatingTest

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.


Solution

  • 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().