SwiftUI로 간단하게 BottomSheet 직접 구현하기

작성일 :

SwiftUI로 간단하게 BottomSheet 직접 구현하기

SwiftUI는 애플이 제공하는 훌륭한 UI 프레임워크로, 직관적이고 깔끔한 코드를 통해 복잡한 UI 요소들을 쉽게 구현할 수 있습니다. 이번 튜토리얼에서는 SwiftUI를 이용하여 간단한 BottomSheet를 직접 구현하는 방법을 알아보겠습니다. BottomSheet는 화면 하단에서 슬라이드로 올라오는 형태의 모달 뷰로, 사용자에게 추가적인 정보를 제공하거나 입력을 받을 때 유용하게 사용됩니다.

기본 SwiftUI 프로젝트 설정

먼저, Xcode에서 새로운 SwiftUI 프로젝트를 생성합니다. 프로젝트가 생성되면 ContentView.swift 파일로 이동합니다. 이곳에 우리의 BottomSheet를 구현할 것입니다.

swift
import SwiftUI

struct ContentView: View {
    @State private var isShowingBottomSheet = false

    var body: some View {
        ZStack {
            VStack {
                Spacer()
                Button(action: {
                    isShowingBottomSheet.toggle()
                }) {
                    Text("Show Bottom Sheet")
                        .font(.headline)
                        .padding()
                        .background(Color.blue)
                        .foregroundColor(.white)
                        .cornerRadius(10)
                }
                .padding(.bottom, 50)
            }
            .zIndex(1)

            if isShowingBottomSheet {
                BottomSheetView(isShowing: $isShowingBottomSheet)
                    .transition(.move(edge: .bottom))
                    .animation(.default)
            }
        }
    }
}

위 코드에서는 isShowingBottomSheet라는 @State 변수를 사용하여 BottomSheet의 표시 여부를 관리하고 있습니다. 버튼을 눌렀을 때 이 변수의 값을 토글하여 BottomSheet를 보여주거나 숨기도록 합니다.

BottomSheetView 구현

이제 실제 BottomSheet의 내용을 담당할 BottomSheetView를 구현해보겠습니다. 이 뷰는 단순한 모달 뷰로 시작하여 디자인과 기능을 추가해 나갈 것입니다.

swift
struct BottomSheetView: View {
    @Binding var isShowing: Bool

    var body: some View {
        VStack {
            Spacer()
            VStack {
                HStack {
                    Spacer()
                    Button(action: {
                        isShowing = false
                    }) {
                        Image(systemName: "xmark")
                            .padding(10)
                            .background(Color.gray)
                            .foregroundColor(.white)
                            .clipShape(Circle())
                    }
                    .padding()
                }
                Text("This is a Bottom Sheet")
                    .font(.headline)
                    .padding()
                Spacer()
            }
            .frame(maxWidth: .infinity)
            .background(Color.white)
            .cornerRadius(30)
            .shadow(radius: 20)
            .padding(.top, 10)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.black.opacity(0.6).edgesIgnoringSafeArea(.all))
        .onTapGesture {
            isShowing = false
        }
    }
}

이 코드에서는 @Binding을 사용하여 부모 뷰 (ContentView)와 상태를 공유합니다. 사용자가 배경을 탭하거나 'x' 버튼을 누르면 모달이 닫히도록 했습니다. 또한, BottomSheet 자체의 디자인 요소들을 추가하여 모달의 모양을 개선했습니다.

BottomSheet 적용 및 확장

이제 BottomSheet가 동작하는지 확인해 보세요. 이 기본 구조를 토대로 다양한 기능을 확장할 수 있습니다. 예를 들어, 리스트 아이템을 추가하거나 폼 입력 필드를 넣을 수 있습니다.

swift
struct ContentView: View {
    @State private var isShowingBottomSheet = false

    var body: some View {
        ZStack {
            VStack {
                Spacer()
                Button(action: {
                    isShowingBottomSheet.toggle()
                }) {
                    Text("Show Bottom Sheet")
                        .font(.headline)
                        .padding()
                        .background(Color.blue)
                        .foregroundColor(.white)
                        .cornerRadius(10)
                }
                .padding(.bottom, 50)
            }
            .zIndex(1)

            if isShowingBottomSheet {
                BottomSheetView(isShowing: $isShowingBottomSheet)
                    .transition(.move(edge: .bottom))
                    .animation(.default)
            }
        }
    }
}

struct BottomSheetView: View {
    @Binding var isShowing: Bool

    var body: some View {
        VStack {
            Spacer()
            VStack {
                HStack {
                    Spacer()
                    Button(action: {
                        isShowing = false
                    }) {
                        Image(systemName: "xmark")
                            .padding(10)
                            .background(Color.gray)
                            .foregroundColor(.white)
                            .clipShape(Circle())
                    }
                    .padding()
                }
                Text("This is a Bottom Sheet")
                    .font(.headline)
                    .padding()
                Spacer()
            }
            .frame(maxWidth: .infinity)
            .background(Color.white)
            .cornerRadius(30)
            .shadow(radius: 20)
            .padding(.top, 10)
        }
        .frame(maxWidth: .infinity, maxHeight: .infinity)
        .background(Color.black.opacity(0.6).edgesIgnoringSafeArea(.all))
        .onTapGesture {
            isShowing = false
        }
    }
}

위 내용처럼 BottomSheetView를 상속받아 다양한 모달 UX를 추가하는 것도 가능합니다. 예를 들어, 사용자에게 보여줄 아이템 목록을 추가하거나, 입력 폼을 넣어 추가 정보를 받을 수 있도록 개발할 수 있습니다.

결론

SwiftUI를 사용하면 간단한 BottomSheet를 쉽게 구현할 수 있습니다. 이 글에서는 기본적인 BottomSheet를 만들고 사용자 인터페이스를 향상시키는 방법을 다루었습니다. SwiftUI의 강력한 기능을 활용하여 더 복잡하고 유용한 모달 뷰를 구현해보세요. SwiftUI는 사용자의 상호작용을 관리하고, 개발자가 효율적인 코드를 작성하는 데 매우 유용한 도구입니다.