[SwiftUI] Custom Tab Bar

Jin·2023년 4월 7일
1
post-thumbnail

앱을 사용하다보면 우리는 다양한 Tab bar를 보게된다.

SwiftUI에서는 TabView를 통해 쉽게 구현할 수 있다.

//TabView
struct ContentView : View {
  var body: some View {
    TabView {
      Text("The First Tab")
        .tabItem {
          Image(systemName: "1.square.fill")
        }
      Text("The Second Tab")
        .tabItem {
          Image(systemName: "2.square.fill")
        }
      Text("The Third Tab")
        .tabItem {
            Image(systemName: "3.square.fill")
        }
    }
  }
}

[SwiftUI의 TabView]

하지만 내가 만들고자 하는 Tab Bar를 구현하기 위해서는 많은 수정이 불가피했다.
다음 동영상을 참고하여 Custom Tab Bar를 구현해보았다.

//Custom TabView
enum Tab {
    case first
    case second
    case third
}

struct ContentView : View {
    @State var selectedTab: Tab = .first
    var body: some View {
        VStack {
            Spacer()
            switch selectedTab {
            case .first:
                Text("The First Tab")
            case .second:
                Text("The Second Tab")
            case .third:
                Text("The Third Tab")
            }
            Spacer()
            CustomTabView(selectedTab: $selectedTab)
        }
    }
}

struct CustomTabView: View {
    @Binding var selectedTab: Tab
    var body: some View {
        HStack {
            Spacer()
            Button() {
                selectedTab = .first
            } label: {
                Image(systemName: "1.square.fill")
            }
            Spacer()
            Button {
                selectedTab = .second
            } label: {
                Image(systemName: "2.square.fill")
            }
            Spacer()
            Button {
                selectedTab = .third
            } label: {
                Image(systemName: "3.square.fill")
            }
            Spacer()
        }
    }
    
}

[Custom TabView]

ZStack을 사용해 동그란 버튼을 만들고 offset으로 위치를 변경하였다.

struct CustomTabView: View {
    @Binding var selectedTab: Tab
    var body: some View {
        HStack {
            Spacer()
            Button() {
                selectedTab = .first
            } label: {
                Image(systemName: "1.square")
            }
            Spacer()
            ZStack {
                Circle()
                    .foregroundColor(Color(.orange))
                    .frame(width: 90, height: 90)
                Button {
                    selectedTab = .second
                } label: {
                    Image(systemName: "2.square")
                }
            }
            .offset(y: -32)
            Spacer()
            Button {
                selectedTab = .third
            } label: {
                Image(systemName: "3.square")
            }
            Spacer()
        }
    }
}

Tab Bar의 배경은 도형을 그리는 것이 익숙치 않아 이미지로 넣어주었고 색상은 Assets에 "Symbol"로 지정하여 사용하였다.
몇가지를 추가로 수정한 코드와 결과는 다음과 같다.

struct CustomTabView: View {
    
    @Binding var selectedTab: Tab
    
    var body: some View {
        ZStack {
            Image("background")
                .resizable()
                .aspectRatio(contentMode: .fill)
                .offset(y: 15)
            HStack {
                Spacer()
                Button {
                    selectedTab = .home
                } label: {
                    Image(systemName: selectedTab == .home ? "house.fill" : "house")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 30)
                        .foregroundColor(.white)
                }
                Spacer()
                Button {
                    selectedTab = .shop
                } label: {
                    ZStack {
                        Circle()
                            .foregroundColor(Color("Symbol"))
                            .frame(width: 90, height: 90)
                        Image(systemName: selectedTab == .shop ? "basket.fill" : "basket")
                            .resizable()
                            .aspectRatio(contentMode: .fit)
                            .frame(width: 40)
                            .foregroundColor(.white)
                    }
                    .offset(y: -32)
                }
                Spacer()
                Button {
                    selectedTab = .profile
                } label: {
                    Image(systemName: selectedTab == .profile ? "person.fill" : "person")
                        .resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: 30)
                        .foregroundColor(.white)
                }
                Spacer()
            }
        }
        .frame(height: 50)
    }
}

profile
= 이 진

0개의 댓글