Just a coder
Just a coder

Reputation: 16730

How to animate switching from one Text to another with swift ui?

I have an array of strings. For example ["Car", "Boat", "Van"]

How do I anime the changing of the text in the array (which can contain more strings) so that it switches from Car to Boat to Van by blurring transition? And so that it continually loops this?

I already have an idea on how to animate, but I was stuck in switching the text. I have asked the question on why the text does not switch over here -> Why does the size animate and not the text with this SwiftUI view?

But I thought It might be better to write a separate question on how to actually switch the text.

Upvotes: 1

Views: 610

Answers (2)

Just a coder
Just a coder

Reputation: 16730

I have already selected @davidev answer. But based on his answer this was what I have implemented. Cheers 🍺

struct ContentView: View {
    var array = ["First", "Second", "Third"]
    @State var currentIndex : Int = 0
    @State var firstString : String = ""
    @State var timer: Timer? = nil
    @State var isBlurred = false
    
    var body: some View {
        VStack {
            Text(firstString).blur(radius: isBlurred ? 6 : 0)
        }.onAppear {
            self.timer = newTimer
        }
    }
    
    var newTimer: Timer {
        Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { v in
            let rndTime = [0.5, 0.3, 0.7, 1.0].randomElement()! // I wanted a random time up to 1 second.
            v.invalidate()
            currentIndex += 1
            if currentIndex == array.count { currentIndex = 0 }
            DispatchQueue.main.asyncAfter(deadline: .now() + rndTime) {
                self.isBlurred.toggle()
                DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
                    self.isBlurred.toggle()
                    firstString = array[currentIndex]
                    self.timer = newTimer
                }
            }
        }
    }
}

Upvotes: 1

davidev
davidev

Reputation: 8517

Here is a possible solution animating text based on an array. I have used Asperis transition idea from this solution here

struct ContentView: View {
    var array = ["First", "Second", "Third"]
    @State var shortString = true
    
    @State var currentIndex : Int = 0
    @State var firstString : String = ""
    @State var secondString : String = ""

    var body: some View {

        VStack {
            if shortString {
               Text(firstString).font(.title).fixedSize()
               .transition(AnyTransition.opacity.animation(.easeInOut(duration:1.0)))
            }
            if !shortString {
                Text(secondString).font(.title).fixedSize()
                    .transition(AnyTransition.opacity.animation(.easeInOut(duration:1.0)))
            }
        }
        .animation(.default)
        .onAppear {
            firstString = array[0]
            secondString = array[1]
            
            let timer = Timer.scheduledTimer(withTimeInterval: 2.0, repeats: true) { _ in
                if (shortString) {
                    if currentIndex == array.count - 1 {
                        self.secondString = array[0]
                        currentIndex = 0
                    }
                    else {
                        self.secondString = array[currentIndex+1]
                        currentIndex += 1
                    }
                }
                else {
                    if currentIndex == array.count - 1 {
                        self.firstString = array[0]
                        currentIndex = 0
                    }
                    else {
                        self.firstString = array[currentIndex+1]
                        currentIndex += 1
                    }
                }
                shortString.toggle()
            }
        }
    }
}

Upvotes: 2

Related Questions