1

I have a list of names that appear vertically thanks to an animation, I would like to have auto-scroll when a new name appears but i don't know how to go on...I saw some questions like this but all of them were a 'jump to a number' solution, not progressively scroll...any suggestions?

enter image description here

UPDATED CODE:

struct ContentView: View {
    let correctNames = ["Steve", "Bill", "John", "Elon", "Michael", "Justin", "Marcell", "David", "Gabriel", "Eric", "Jeffrey", "Taylor", "Jennifer", "Christian"]
    @State private var animating = false
    
    var body: some View {
        VStack {
            ScrollView(showsIndicators: false) {
                ForEach(0..<correctNames.count, id: \.self) { index in
                    Text("\(correctNames[index])")
                        .font(.system(size: 60))
                        .opacity(animating ? 1 : 0)
                        .animation(.easeIn(duration: 0.5).delay(Double(index) * 0.2), value: animating)
                }
            }
        }
        .onAppear {
            animating.toggle()
        }
    }
}
1
  • 1
    Use scroll view reader is the closet thing in SwiftUI. Using UIKit you can be more meticulous, there isn’t anything built in Commented Aug 17, 2022 at 18:01

1 Answer 1

1

I would do all this in different approach, model-driven and per-item, to have more control on effects.

A possible approach, is to add items into source of truth one by one and add effects depending on this collection growing.

Here is a demo. Tested with Xcode 14 / iOS 16

demo

Main parts:

@State private var items = [Int]()   // storage

...

ScrollViewReader { sr in
    ScrollView(showsIndicators: false) {
      // ...
    }
}
.onAppear {
    items.append(1)   // initial item put
}

...

// iterating model ...
ForEach(items, id: \.self) { index in
    // content
    Text("\(index)").id(index).font(.system(size: 64))
    // ... it is appeared, so we can use transition
        .transition(index == items.last ? .opacity : .identity)
        .onAppear {
            // on last appeared scedule add next ...
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.82) {
                if index == items.last && index < 50 {
                    items.append(index + 1)
                }
                DispatchQueue.main.async {
                    // ... and animate scrolling to it after add
                    withAnimation {
                        sr.scrollTo(index + 1)
                    }
                }
            }
        }

Test code is here

Sign up to request clarification or add additional context in comments.

1 Comment

I updated my code with an array of string that is not empty, can you update the answer?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.