swiftuiswiftui-listswiftui-scrollviewlazyvstack

Get current item in LazyVstack inside scrollview when scroll ends


I want to print the currently displayed item in LazyVStack which is inside scrollview with paging enabled.

i have tried printing in onAppear of VerseView The issues with printing inside onAppear are-

I SIMPLY WANT TO PRINT THE CURRENT ITEM WHICH IS DISPLAYED IN SCREEN WHENEVER I RELEASES THE SCROLL.

CODE IS :

    struct SwippableView: View {
    var data: [VerseModel]
  
    
    var body: some View {
        
        ScrollView(.vertical) {
            LazyVStack(spacing: 0) {
                ForEach(data, id: \.id) { verse in
                   
                    VerseView(verse: verse)
                        .padding(0)
                        .frame(maxWidth: .infinity, maxHeight: .infinity)
                    
                }
            }.scrollTargetLayout()
                
        }
        .ignoresSafeArea()
        .scrollTargetBehavior(.paging)
        .scrollIndicators(.never)
        
    }
}

Additional info: Each view inside LazyVStack fills the entire screen


Solution

  • Try this approach using .scrollPosition and a .onChange to print the current verse that is on the screen when scrolling.

    struct ContentView: View {
        // --- for testing
        let verses = [VerseModel(id: 1, verse: "verse-1"), VerseModel(id: 2, verse: "verse-2"), VerseModel(id: 3, verse: "verse-3")]
        var body: some View {
            SwippableView(data: verses)
        }
    }
    
    // --- for testing
    struct VerseModel: Identifiable, Hashable {
        let id: Int
        var verse: String
    }
    
    struct SwippableView: View {
        var data: [VerseModel]
        @State var scrolledID: Int?  // <--- here
    
        var body: some View {
            Text("\(scrolledID ?? 1)")  // <--- for testing
            ScrollView(.vertical) {
                LazyVStack(spacing: 0) {
                    ForEach(data, id: \.id) { verse in
                        VerseView(verse: verse)
                            .frame(maxWidth: .infinity, maxHeight: .infinity)
                    }
                }.scrollTargetLayout()
            }
            .ignoresSafeArea()
            .scrollTargetBehavior(.paging)
            .scrollIndicators(.never)
            .scrollPosition(id: $scrolledID) // <--- here
            .onChange(of: scrolledID) {
                print("----> scrolledID: \(scrolledID)")  // <--- here
            }
        }
    }
    
    // --- for testing
    struct VerseView: View {
        var verse: VerseModel
        
        var body: some View {
            ZStack {
                Rectangle().fill(Color.red.opacity(0.3))
                Text(verse.verse)
            }.frame(width: 333, height: 666)
        }
    }