iosswiftxcodeswiftui

Why is .transition not applied on SwiftUI Text view when text (and ID) change?


In the following example the text and with it the ID of the Text view changes, when the button is tapped. So SwiftUI should treat the Text view as new view due to the updated ID, should it? So why is the transition not triggerd?

struct TextTransitionView: View {
    @State private var text: String = "Hello, World!"
    
    private var textTransition: AnyTransition {
        .asymmetric(
            insertion: .move(edge: .bottom).combined(with: .opacity),
            removal: .move(edge: .top).combined(with: .opacity)
        )
    }
    
    var body: some View {
        VStack {
            Text(text)
                .transition(textTransition)
                .id(text)
            
            Button("Change Text") {
                self.text += "!"
            }
        }
    }
}

Solution

  • Make it a newview every cycle:

    struct TextTransitionView: View {
        @State private var text: String = "Hello, World!"
        
        private var textTransition: AnyTransition {
            .asymmetric(
                insertion: .move(edge: .bottom).combined(with: .opacity),
                removal: .move(edge: .top).combined(with: .opacity)
            )
        }
        
        var body: some View {
            VStack {
                Text(text)
                    .transition(textTransition)
                    .id(text)  // Ensures the Text view has a new identity
    
                Button("Change Text") {
                    withAnimation {
                        self.text += "!"
                    }
                }
            }
        }
    }