Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save woozoobro/29f92555b383ba20945b32a9076a4c47 to your computer and use it in GitHub Desktop.

Select an option

Save woozoobro/29f92555b383ba20945b32a9076a4c47 to your computer and use it in GitHub Desktop.
SwiftUI Custom TabView

커스텀한 탭바 만들기

커스텀한 탭바를 만드는 방법엔 다양한 방법들이 있습니다!

PreferenceKey를 이용해서 자식의 뷰가 업데이트 될 때, 부모의 뷰가 이 것을 알아차리고 스스로를 업뎃할 수 있게 구성해줄 수도 있고

아니면 오늘 만들어볼 SwiftUI의 기본 TabView 컴포넌트랑 함께 커스텀하게 만든 뷰를 위에 올려서 구성해줄 수도 있어요!

두가지 방법을 다 구현해봤었는데 아래 방법이 제일 깔끔한 것 같더라구요


먼저 탭뷰로 보여질 CustomTabView 구성하기!

enum Tab: String, CaseIterable {
    case home = "house.fill"
    case forum = "message.fill"
    case study = "folder.fill"
    case profile = "person.circle.fill"
    
    var titleText: String {
        switch self {
            case .home: return ""
            case .forum: return "게시판"
            case .study: return "스터디"
            case .profile: return "프로필"
        }
    }
}

Tab의 Selection이 될 enum 을 선언해줬습니다 그리고 rawValue로 sf symbol 이미지를 가져올 수 있게 해줬어요!

다음은 CustomTabBar를 가지고 있을 컨테이너뷰! 이 뷰가 제일 앞단에 보여질거에요

struct CustomTabBar: View {
    @State var currentTab: Tab = .home
    
    var body: some View {
        HStack(spacing: 0) {
            ForEach(Tab.allCases, id: \.rawValue) { tab in
                Button {
                    withAnimation(.spring()) {
                        currentTab = tab
                    }
                } label: {
                    VStack(spacing: 1) {
                        Image(systemName: tab.rawValue)
                            .font(.subheadline).bold()
                            .scaleEffect(currentTab == tab ? 1.1 : 0.9)
                            .frame(maxWidth: .infinity)
                            .background {
                                Capsule()
                                    .fill(currentTab == tab ? .green : .clear)
                                    .frame(width: currentTab == tab ? 60 : 0)
                                    .frame(height: 2.2)
                                    .offset(y: -17)
                            }
                        
                        Text(tab.titleText)
                            .font(.caption)
                    }
                    .foregroundColor(currentTab == tab ? .green : .gray)
                }
                .buttonStyle(TabButtonStyle())
            }
        }
        .frame(height: 30)
        .padding(.top, 10)
        .padding(.bottom, 8)
        .background(.ultraThinMaterial)
    }
}

Button Style

struct TabButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .scaleEffect(configuration.isPressed ? 0.8 : 1.0)
    }
}

(View의 extension으로 만들면 더 깔끔하게 쓸 수 있습니다!!)

extension View {
	func customButtonStyle() -> some View {
		self.buttonStyle(TabButtonStyle())
	}
}

SwiftUI 기본 TabView

struct ContentView: View {
    @State private var currentTab: Tab = .home
    
    var body: some View {
        TabView(selection: $currentTab) {
            Text("홈뷰")
                .tag(Tab.home)                
            
            Text("게시판뷰")
                .tag(Tab.forum)
            
            Text("스터디뷰")
                .tag(Tab.study)
            
            Text("프로필뷰")
                .tag(Tab.profile)
            
        }
    }
}

여기다가 아까 만든 뷰를 위에 올려버리는 거에요

struct ContentView: View {
    @State private var currentTab: Tab = .home
    
    init() {
        UITabBar.appearance().isHidden = true
    }
    
    var body: some View {
        ZStack(alignment: .bottom) {
            TabView(selection: $currentTab) {
                Text("홈뷰")
                    .tag(Tab.home)
                
                Text("게시판뷰")
                    .tag(Tab.forum)
                
                Text("스터디뷰")
                    .tag(Tab.study)
                
                Text("프로필뷰")
                    .tag(Tab.profile)
            }
            .toolbar(.hidden, for: .tabBar)
            
            CustomTabBar(currentTab: $currentTab)
        }
    }
}

탭이 이미 선택이 된 상태일 때 다시 탭을 하면 ScrollViewReader를 이용해서 Scroll이 되게끔 구성해주는 것도 구현해볼 거고

최신 표현인! NavigationStack을 사용해서 코드에서 Pop To Root 같은 것을 쉽게 구현해보기도 하고,

이런 Navigation과 Tab을 관리해주는 객체를 만들어서 조금 더 효율적으로 이런 UI를 구성해보는 것도 만들어볼 예정입니다

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment