skip to Main Content

I have an array of string and of course when the view appears, the ForEach shows all the items at once, but I would like to show one item at a time, i think i should do it using an animation but i don’t know how to go on…

This is the effect i’m trying to achieve:

enter image description here

This is my simple code:

struct ContentView: View {
    let correctNames = ["Steve", "Bill", "Elon", "Paul"]
    
    var body: some View {
        VStack {
            ForEach(correctNames, id: .self) { name in
                Text("(name)")
                    .font(.largeTitle)
                    .bold()
            }
        }
    }
}

2

Answers


  1. Simple approach.

    Use a timer and a counter. Increment the counter every second and show the items 0 to counter animated. If the counter reaches the size of the array cancel the timer.

    struct ContentView: View {
        let correctNames = ["Steve", "Bill", "Elon", "Paul"]
        let timer = Timer.publish(every: 1.0, on: .main, in: .common).autoconnect()
        @State private var counter = 0
        
        var body: some View {
            VStack {
                ForEach(0...counter, id: .self) { index in
                    Text(correctNames[index])
                        .font(.largeTitle)
                        .bold()
                }
            }
            .onReceive(timer) { _ in
                withAnimation {
                    if counter < correctNames.count - 1 {
                        counter = counter + 1
                    } else {
                        timer.upstream.connect().cancel()
                    }
                }
            }
        }
    }
    
    Login or Signup to reply.
  2. Here’s a different take. Use .opacity() to hide/show the names, and give each view an increasing delay. When animating is toggled with onAppear, the views will show one by one.

    struct ContentView: View {
        @State private var animating = false
        let correctNames = ["Steve", "Bill", "Elon", "Paul"]
        
        var body: some View {
            VStack {
                ForEach(0..<correctNames.count, id: .self) { index in
                    Text("(correctNames[index])")
                        .font(.largeTitle)
                        .bold()
                        .opacity(animating ? 1 : 0)
                        .animation(.default.delay(Double(index)), value: animating)
                }
            }
            .onAppear { animating.toggle() }
        }
    }
    

    If you want to make the fade in longer, replace the .animation() line with:

    .animation(.easeIn(duration: 0.9).delay(Double(index)), value: animating)
    

    To increase or decrease the time between names, multiply Double(index) by the number of seconds you want.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search