Search code examples
iosswiftswiftuiswiftui-list

How to get on screen rows from List in SwiftUI?


I'm trying to put a Text for each visible (within the screen bounds) row in a List of their current index in all the visible rows.

I have an example here. If I have a list showing 3 rows at a time, and initially I want it showing like this:

___|___
A  |  0
B  |  1
C  |  2
-------

And if I scroll the list down, and A goes out of the screen, then it will be like

___|___
B  |  0
C  |  1
D  |  2
-------

Any idea how can I do it?

Besides, I used to use UITableView.visibleCells to obtain the visible cells on screen, but I couldn't find something similar in SwiftUI. How exactly am I suppose to get visible row in a list with only index provided in SwiftUI?

Hope someone can direct me to the right place. Thanks a lot!


Solution

  • You can use onAppear and onDisappear functions to maintain a list of visible rows and then use these to find a visible index.

    struct ContentView: View {
        let rows = (Unicode.Scalar("A").value...Unicode.Scalar("Z").value)
            .map { String(Unicode.Scalar($0)!) }
    
        @State var visibleRows: Set<String> = []
    
        var body: some View {
            List(rows, id: \.self) { row in
                HStack {
                    Text(row)
                        .padding(40)
                        .onAppear { self.visibleRows.insert(row) }
                        .onDisappear { self.visibleRows.remove(row) }
                }
                Spacer()
                Text(self.getVisibleIndex(for: row)?.description ?? "")
            }
        }
    
        func getVisibleIndex(for row: String) -> Int? {
            visibleRows.sorted().firstIndex(of: row)
        }
    }