Search code examples
swiftuiswift-playground

How do I add sections to list and have section scroll on the side


I’m a noob at this and need help. I’m trying to have my list alphabetically organized and have it divided into sections by letter. Also I want the user to have an option to have section scroller on the side. Pretty much I want it to look and work as contacts app. Is there an easy way to code it into my app?

Also my app is going to be in Russian

struct ContentView: View {
var psalms: [Psalm] = PsalmData.topTen
var body: some View {
    NavigationView {
        List (psalms, id: \.id){ psalm in
                NavigationLink(destination: PsalmDetail(psalm: psalm)) {
                    Text(psalm.title)
                        .lineLimit(1)
                }
                .navigationTitle(Text("Оглавление"))
                .navigationBarTitleDisplayMode(.inline)
        }
    }
}
struct Psalm: Identifiable {
let id = UUID()
let title: String
let letter: String
let location: String
let object: String 

struct PsalmData{

static let topTen = [
    Psalm(title: "А КОГДА ОН ПРИБЛИЗИЛСЯ",
          letter: "А",
          location: "Лук 19.37-40",
          object: "А когда Он приблизился к спуску с горы Елеонской, все множество учеников начало в радости велегласно славить Бога за все чудеса, какие видели они, говоря: благословен Царь, грядущий во имя Господне мир на небесах и слава в вышних! И некоторые фарисеи из среды народа сказали Ему: Учитель! Запрети ученикам Твоим. Но Он сказал им в ответ: сказываю вам, что если они умолкнут то камни возопиют."),
    Psalm(title: "БЛАЖЕН МУЖ",
          letter: "Б",
          location: "Пс.1",
          object: "Блажен муж, который не ходит на совет нечестивых и не стоит на пути грешных и не сидит в собрании развратителей, но в законе Господа воля его, и о законе Его размышляет он день и ночь! И будет он как дерево, посаженное при потоках вод, которое приносит плод свой во время свое, и лист которого не вянет; и во всем, что он ни делает, успеет. Не так - нечестивые; но они - как прах, возметаемый ветром с лица земли. Потому не устоят нечестивые на суде, и грешники – в собрании праведных. Ибо знает Господь путь праведных, а путь нечестивых погибнет."),
    Psalm(title: "БОЖЕ МОЙ! БОЖЕ МОЙ!",
          letter: "Б",
          location: "Пс.21.2-5",
          object: "Боже мой! Боже мой! для чего Ты оставил меня? Далеки от спасения моего слова вопля моего. Боже мой! я вопию днем, - и Ты не внемлешь мне, ночью, — и нет мне успокоения. Но Ты, Святый, живешь среди славословий Израиля. На Тебя уповали отцы наши; уповали, и Ты избавлял их."),
]

Btw I’m doing this on iPad with swift playgrounds


Solution

  • I think the best way is to use a grouped list with alphabetical dictionaries. Alphabetically sectioned list

    To get a scroll bar you can wrap the List in a ScrollViewReader. Then add an id (.id(_ id: Hashable) on each section. With this, you’re able to scroll to the sections.

    scrollViewProxy.scrollTo(_ id :Hashable)
    

    Combine this with sectioning with the dictionary:

    struct AlphabeticalList: View {
    var abc: [String] = ["a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p",]
    
    var body: some View {
        ScrollViewReader { scrollViewProxy in
            List {
                ForEach(abc, id: \.self) { section in
                    Section(section) {
                        Text(section)
                    }
                    .id(section)
                }
            }
            .overlay(alignment: .trailing) {
                VStack {
                    ForEach(abc, id: \.self) { section in
                        Button(section) {
                            scrollViewProxy.scrollTo(section, anchor: .top)
                        }
                    }
                }
            }
        }
    }
    }