SwiftUI List with Section Index on right hand side?

前端 未结 4 1070
旧时难觅i
旧时难觅i 2021-02-03 13:23

Is it possible to have a List with an index on the right hand side, like the example below in SwiftUI?

\"Example\"<

4条回答
  •  悲哀的现实
    2021-02-03 13:42

    See the solution provided on this page by DirectX and please consider giving it an upvote. It is the correct answer.

    I've taken his View and created a ViewModifier you can use with any view that consists of a SwiftUI List with Sections (tableview).

    Just be sure to provide a list of header (section) titles that corresponds to the headers in the view you are adding the index to. Click on the letter to scroll to that section of the list. Notice that I only provide the indexes I can actually scroll to when calling the view modifier.

    Use like any view modifier:

    SimpleDemoView().modifier(VerticalIndex(indexableList: contacts))
    

    Here's the code for the modifier:

    struct VerticalIndex: ViewModifier {
        let indexableList: [String]
        func body(content: Content) -> some View {
            var body: some View {
                ScrollViewReader { scrollProxy in
                    ZStack {
                        content
                        VStack {
                            ForEach(indexableList, id: \.self) { letter in
                                HStack {
                                    Spacer()
                                    Button(action: {
                                        withAnimation {
                                            scrollProxy.scrollTo(letter)
                                        }
                                    }, label: {
                                        Text(letter)
                                            .font(.system(size: 12))
                                            .padding(.trailing, 7)
                                    })
                                }
                            }
                        }
                    }
                }
            }
            return body
        }
    }
    

    Here's what it looks like using the sample provided by DirectX:

    For completeness, here's code to reproduce the display:

    struct SimpleDemo_Previews: PreviewProvider {
        
        static var previews: some View {
            
            SimpleDemoView().modifier(VerticalIndex(indexableList: contacts))
        }
    }
    
    struct SimpleDemoView: View {
        var body: some View {
            List {
                ForEach(alphabet, id: \.self) { letter in
                    Section(header: Text(letter).id(letter)) {
                        ForEach(contacts.filter({ (contact) -> Bool in
                            contact.lastName.prefix(1) == letter
                        })) { contact in
                            HStack {
                                Image(systemName: "person.circle.fill").font(.largeTitle).padding(.trailing, 5)
                                Text(contact.firstName)
                                Text(contact.lastName)
                            }
                        }
                    }
                }
            }
            .navigationTitle("Contacts")
            .listStyle(PlainListStyle())
    
        }
    }
    

    Here's the sample data used to provide the demo (modified from DirectX's solution):

    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"] //swiftlint:disable comma
    
    let contacts: [Contact] = {
        var contacts = [Contact]()
            contacts.append(Contact(firstName: "Chris", lastName: "Ryan"))
            contacts.append(Contact(firstName: "Allyson", lastName: "Ryan"))
            contacts.append(Contact(firstName: "Jonathan", lastName: "Ryan"))
            contacts.append(Contact(firstName: "Brendan", lastName: "Ryaan"))
            contacts.append(Contact(firstName: "Jaxon", lastName: "Riner"))
            contacts.append(Contact(firstName: "Leif", lastName: "Adams"))
            contacts.append(Contact(firstName: "Frank", lastName: "Conors"))
            contacts.append(Contact(firstName: "Allyssa", lastName: "Bishop"))
            contacts.append(Contact(firstName: "Justin", lastName: "Bishop"))
            contacts.append(Contact(firstName: "Johnny", lastName: "Appleseed"))
            contacts.append(Contact(firstName: "George", lastName: "Washingotn"))
            contacts.append(Contact(firstName: "Abraham", lastName: "Lincoln"))
            contacts.append(Contact(firstName: "Steve", lastName: "Jobs"))
            contacts.append(Contact(firstName: "Steve", lastName: "Woz"))
            contacts.append(Contact(firstName: "Bill", lastName: "Gates"))
            contacts.append(Contact(firstName: "Donald", lastName: "Trump"))
            contacts.append(Contact(firstName: "Darth", lastName: "Vader"))
            contacts.append(Contact(firstName: "Clark", lastName: "Kent"))
            contacts.append(Contact(firstName: "Bruce", lastName: "Wayne"))
            contacts.append(Contact(firstName: "John", lastName: "Doe"))
            contacts.append(Contact(firstName: "Jane", lastName: "Doe"))
        return contacts.sorted()
    }()
    
    let indexes = Array(Set(contacts.compactMap({ String($0.lastName.prefix(1)) }))).sorted()
    

提交回复
热议问题