【SwiftUI】InsetGroupedListStyle()을 사용하여 개폐 가능한 List를 만들고 싶습니다.

10827 단어 iOSSwiftSwiftUI

소개



List에는 여러 종류가 있습니다만, 그 중에서도 InsetGroupedListStyle() 가 마음에 듭니다.
그 밖에 어떤 UI의 List가 있을까는, 「 【SwiftUI】List 사용법 」라고 하는 것을 확인해 주세요.

SwiftUI로 구현하는데 있어서 항상 참고로 하겠습니다.

이번은, UI는 InsetGroupedListStyle()입니다만, SidebarListStyle() 와 같이 개폐할 수 있는 List를 구현하고 싶었으므로, 그것을 소개합니다.
SidebarListStyle() 를 그대로 사용하면 셀의 오른쪽에 chevron이 존재한다고 생각합니다만, 그 아이콘이나 거동도 커스터마이즈하고 싶었으므로, 결국 InsetGroupedListStyle() 를 사용한 구현이 되었습니다.

아티팩트



다음을 할 수 있습니다.
  • Section을 눌렀을 때 개폐한다
  • 열려 있거나 닫힐 때 표시되는 아이콘 (화살표) 변경
  • 열려 있거나 닫힐 때 섹션 아래의 (코드에 있으면 섹션 안에 있음) 선 표시를 전환합니다.

    동영상에서 보고 싶다면 아래의 Github 리포지토리에 게시하고 있으므로 해당 README를 확인하세요.



    구현


    struct ContentView: View {
        // テスト用データ(APIから取得したデータを格納したり、、今回は辞書を使っているので順番が保証されないのに注意)
        private let testData = ["食べ物": ["明太子パスタ", "ショートケーキ", "プロシュート", "パウンドケーキ"], "飲み物": ["コーラ", "ルイボスティー"]]
    
        // 選択されたSectionがどれかを格納しておくためのSet
        @State private var selection: Set<String> = []
    
        var body: some View {
            let keys: [String] = testData.map { $0.key }
            let values: [[String]] = keys.compactMap { testData[$0] }
    
            VStack {
                List {
                    ForEach(keys.indices) { keyIndex in
                        Section(header: sectionHeader(title: keys[keyIndex], isExpanded: self.selection.contains(keys[keyIndex]))) {
    
                            if self.selection.contains(keys[keyIndex]) {
                                ForEach(values[keyIndex].indices) { valueIndex in
                                    Text(values[keyIndex][valueIndex])
                                        .foregroundColor(Color.black)
                                }
                            }
                        }
                    }
    
                }
                .listStyle(InsetGroupedListStyle())
            }
        }
    }
    
    extension ContentView {
        private func sectionHeader(title: String, isExpanded: Bool) -> some View {
            Button(action: {self.selectDeselect(selectedSection: title)}) {
                VStack {
                    HStack {
                        Text(title)
    
                        Spacer()
    
                        Image(systemName: isExpanded ? "chevron.up" : "chevron.down")
                    }
    
                    if !isExpanded {
                        Divider()
                    } else {
                        Divider()
                            .frame(height: 0)
                    }
                }
            }
            .foregroundColor(Color.gray)
        }
    
        // Sectionが押下された時に、Setの中身を変更するメソッド
        private func selectDeselect(selectedSection: String) {
            if selection.contains(selectedSection) {
                selection.remove(selectedSection)
            } else {
                selection.insert(selectedSection)
            }
        }
    }
    

    코멘트에도 쓰고 있습니다만, 이번은 표시하는 데이터가 격납하는 형태가, Dictionary이므로 차례는 보증되고 있지 않습니다.
    순서를 보증하고 싶은 경우는, 다른 데이터형을 사용하지 않으면 안됩니다만, 이번은 샘플이므로 양해. .

    Set 형을 준비해, 거기에 선택된 Section 의 캐릭터 라인을 보관 유지하고 있습니다.
    이번에는 「음식」 「음료」등이 들어 있습니다만, 아마 ID라든지 좀 더 고유한 값이 좋다고는 생각합니다.

    참고한 기사


  • [SwiftUI] [String: [String]]을 섹션으로 나누어 표시
  • Expand and Collapse List Rows with Animation in SwiftUI

  • 끝에



    아직 SwiftUI 공부중의 몸이므로, 실은 SidebarListStyle() 를 사용해 좀 더 잘 할 수 있을지도 모릅니다. 보다 좋은 방법을 아시는 분, 꼭 코멘트로 가르쳐 주세요!

    좋은 웹페이지 즐겨찾기