Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI Jump Menu (sectionIndexTitles)

Tags:

ios

swift

swiftui

I have an alphabetically sorted SwiftUI List with sections. I try to set a jump menu / sidebar for scrolling through the sections like here:

Screenshot with jump menu

In UIKit it was possible by setting the sectionIndexTitles. But I couldn't find a solution for SwiftUI.

like image 792
Eduard Avatar asked Sep 12 '25 10:09

Eduard


1 Answers

What you can do in SwiftUI 2.0 is to use the ScrollViewReader.

First, in your list, each element has to have a unique ID which can be any hashable object. Simply use the .id modifier. For example:

List(0..<10) { i in
   Text("Row \(i)")
   .id(i)
}

After that you can use the ScrollViewReader as following:

ScrollViewReader { scroll in
    VStack {
        Button("Jump to row #10") {
             scroll.scrollTo(10)
        }

        List(0..<10) { i in
             Text("Row \(i)")
             .id(i)
        }
     }
  }

So in your case you could give the each alphabetical section an id, so section "a" would have .id(a) etc. After that you could use the sidebar you've implemented and jump to the desired alphabetical section inside ScrollViewReader.

Edit: So I have tried to make a very simple solution quickly. It is not perfect but it serves your purpose. Feel free to copy and modify the code:

struct AlphaScroller: View {

let alphabet = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z"]

let sampleItems = ["Apple", "Banana", "Orange"]

var body: some View {
    ScrollView {
        ScrollViewReader{ scroll in
            VStack {
                
                //top character picker with horizontal Scrolling
                ScrollView(.horizontal) {
                    HStack(spacing: 20) {
                        ForEach(alphabet, id: \.self) { char in
                            Button(char){
                                withAnimation {
                                    scroll.scrollTo(char, anchor: .top)
                                }
                            }
                        }
                    }
                }.frame(width: UIScreen.main.bounds.width * 0.8, height: 20)
                
                //list of sections
                ForEach(alphabet, id: \.self){ char in
                    HStack {
                        VStack {
                            Text(char).id(char)
                                .font(.system(size: 30))
                                .padding()
                            
                            ForEach(sampleItems, id: \.self){ item in
                                Text(item)
                                    .padding()
                            }
                            
                            Rectangle()
                                .foregroundColor(.gray)
                                .frame(width: UIScreen.main.bounds.width, height: 1)
                        }
                        Spacer()
                    }
                }
            }
        }
    }
}

}

like image 115
Alexandr Čížek Avatar answered Sep 15 '25 00:09

Alexandr Čížek