seong_hye, the developer

Swift) List 속 DropDown 사용하기 본문

IOS/SwiftUI

Swift) List 속 DropDown 사용하기

seong_hye 2023. 7. 20.

📘List Drop Down

List 내 항목을 눌렀을 때 드롭다운처럼 하위 항목이 펼쳐지는 UI

Expandable List 또는 Accordion List라고 부름

각 항목의 펼침 상태를 추적하는 플래그가 필요함


🔹항목 모델 정의

struct DataModel {
    let iconName: String
    let title: String
    var destination: AnyView
}

struct DropdownItem: Identifiable {
    let id = UUID()
    let title: TitleModel
    let details: [DataModel]
    var isExpanded: Bool = false
}

🔹메인 뷰 - List를 활용한 DropDown

@Binding var dropDownList: [DropdownItem]
    
var body: some View {
	List {
        ForEach(dropDownList.indices, id: \.self) { index in
            Section {
                Button(action: {
                    withAnimation {
                        dropDownList[index].isExpanded.toggle()
                    }
                }) {
                    HStack {
                        Text(dropDownList[index].title.title)
                        Spacer()
                        Image(systemName: dropDownList[index].title.iconName)
                            .foregroundColor(.gray)
                    }
                }
                    
                if dropDownList[index].isExpanded {
                    ForEach(dropDownList.indices, id: \.self) { detail in
                        HStack {
                            Text(dropDownList[index].details[detail].title)
                            Spacer()
                            Image(systemName: dropDownList[index].details[detail].iconName)
                                .foregroundColor(.gray)
                        }
                    }
                }
            }
        }
    }
    .listStyle(InsetGroupedListStyle())
}

➡️ 설명

List를 통해 정의된 dropDownList를 받아

해당 index의 title이 선택되는 경우 isExpanded 값을 true로 변경시켜

아래의 detail list가 보이도록 함

 

➡️ 결과 화면


🔹메인 뷰 -  사용자 정의에 따른 DropDown

var icon: String
var title: String
var color: Color
var dropDownList: [DataModel]
    
@State private var showList = false
    
var body: some View {
    VStack {
        ZStack {
            HStack {
                Image(systemName: icon)
                    .frame(width: 30)
                Text(title)
                    .font(.title2)
                Spacer()
                Image(systemName: "chevron.forward")
                    .font(.system(size: 15))
                    .foregroundStyle(.white)
                    .rotationEffect(.degrees(showList ? 90 : 0))
            }
            .bold()
            .foregroundStyle(.white)
            .padding()
            .frame(maxWidth: .infinity)
            .frame(height: 53)
            .background(color, in: RoundedRectangle(cornerRadius: 15))
            .onTapGesture {
                withAnimation {
                    showList.toggle()
                }
            }
            .zIndex(1)

            ForEach(dropDownList.indices, id: \.self) { item in
                NavigationLink {
                    dropDownList[item].destination
                } label: {
                    HStack {
                        Image(systemName: dropDownList[item].iconName)
                            .frame(width: 30)
                        Text(dropDownList[item].title)
                        Spacer()
                        Image(systemName: "arrow.right")
                    }
                    .foregroundStyle(.white)
                    .frame(maxWidth: .infinity)
                    .padding()
                    .background(color.opacity(showList ? 1 :(1 - Double(item) * 0.3)), in: RoundedRectangle(cornerRadius: 15))
                    .padding(.leading, 15)
                }
                .offset(y: showList ? CGFloat(item * 58) : CGFloat(item * 8))
                .scaleEffect(showList ? 1 : (1 - Double(item) * 0.04))
                .zIndex(CGFloat(item * -1))
            }
            .offset(y: showList ? 58 : 0)
        }
        .padding(.horizontal)
        Spacer()
    }
    .frame(height: showList ?  CGFloat(dropDownList.count * 80) : 70)
}

➡️ 설명

사용자 정의에 따라 원하는 뷰를 하나 제작하여 보이도록 함
뷰를 클릭했을 경우 showList 값을 활용해 detail 값이 보이도록 함

배열로 받은 detail값의 index를 이용하여 뷰의 색상과 보이는 높이와 넓이를 조절

 

➡️ 결과 화면


 

참조 : https://www.youtube.com/watch?v=4kjPOw_pjx0 

 


 

Comments