[SwiftUI] TabView를 활용한 멀티스크린

리벤쿤·2024년 1월 17일

iOS 앱 개발

목록 보기
2/2

Modal, Navigation, Tab을 응용하여 나만의 화면을 만드는 실습을 진행해봤다.

구현하고자 하는 앱의 화면

  1. 앱 실행 시 팝업 형태의 OnBoard로 안내창이 등장한다. Swipe 동작으로 넘길 수 있으며, 마지막 페이지에는 'Continue' 버튼이 있어 팝업을 끌 수 있다.
  2. 하단 Tab에서 Received, Send, Account를 선택할 수 있으며, 아이템은 이미지와 텍스트로 구성된 Label을 활용한다.
  3. Received 탭은 List 형태로 되어있으며, 각 항목은 Navigation으로 구성되어있다. 클릭하면 해당 페이지로 넘어가며, Navigation Stack 형태로 이루어져 있어 다시 Received 탭으로 돌아올 수 있다.

1. Tab View : Onboard Modal

온보드 모달로 사용할 화면을 SwiftUI 파일로 생성한다. ZStack으로 배경 색상을 지정하고, 그 안에 VStack으로 이미지 및 텍스트를 설정한다.

import SwiftUI

struct OnBoardingSample: View {
    
    let onboardingTitle: String
    let imageSystemName: String
    
    var body: some View {
        ZStack {
            Color.gray.ignoresSafeArea()
            VStack {
                Image(systemName: imageSystemName)
                    .resizable()
                    .scaledToFit()
                    .frame(width: 100)
                    .foregroundColor(.white)
                Text(onboardingTitle)
                    .padding()
                    .font(/*@START_MENU_TOKEN@*/.title/*@END_MENU_TOKEN@*/)
                    .foregroundColor(.white)
            }
        }
    }
}

#Preview {
    OnBoardingSample(onboardingTitle: "This is Detail!", imageSystemName: "square.and.arrow.up")
}

버튼이 있는 마지막 모달 페이지는 다음과 같은 작업을 추가로 하면 된다.
1. 메인 화면에서 온보드 패널들이 보여지고 있는지를 뜻하는 bool 변수를 바인딩
2. VStack 안에 버튼 생성 후, 위의 바인딩한 변수의 값을 true로 변경
3. 해당 파일 생성자에 bool 변수에 대한 초기값을 .constant(true)로 설정

OnBoard의 하단에 페이지의 개수와 현재 위치를 보여주기 위해서는 indexDisplayMode의 설정을 다음과 같이 하면 된다.

.tabViewStyle(.page(indexDisplayMode: .always))

앱을 생성할 메인 파일에서는 다음과 같이 작성한다.

struct MyApp: View {
    
    @State var showModal = false
    
    var body: some View {
        TabView {
        // Received
        // Send
        // Account
        }
        .sheet(isPresented: $showModal, content: {
            TabView {
                OnBoardingSample(onboardingTitle: "OnBoard 1", imageSystemName: "1.lane")
                OnBoardingSample(onboardingTitle: "OnBoard 2", imageSystemName:  "2.lane")
                OnBoardingWithButton(isPresented: $showModal, onboardingTitle: "OnBoard 3", imageSystemName: "3.lane")
            }
            .tabViewStyle(.page(indexDisplayMode: .always))
        })
        .onAppear() {
             showModal = true
        }
    }
}

2. Tab View

하단에 탭을 생성하기 위한 코드다. 위 TabView의 경우 설정을 따로 했지만, 기본적으로는 하단에 탭뷰 아이템들이 순서대로 그려진다.

struct MyApp: View {
    
    @State var showModal = false
    
    var body: some View {
        TabView {
        		// 추후 List 페이지로 수정 
            	Text("Received")
                    .tabItem {
                        Label("Received", systemImage: "tray.and.arrow.down.fill")
                    }
                
                Text("Send")
                    .tabItem {
                        Label("Send", systemImage: "tray.and.arrow.up.fill")
                    }
                
                Text("Account")
                    .tabItem {
                        Label("Account", systemImage: "person.crop.circle.fill")
                    }
        }
        .sheet(isPresented: $showModal, content: {
            TabView {
                OnBoardingSample(onboardingTitle: "OnBoard 1", imageSystemName: "1.lane")
                OnBoardingSample(onboardingTitle: "OnBoard 2", imageSystemName:  "2.lane")
                OnBoardingWithButton(isPresented: $showModal, onboardingTitle: "OnBoard 3", imageSystemName: "3.lane")
            }
            .tabViewStyle(.page(indexDisplayMode: .always))
        })
        .onAppear() {
             showModal = true
        }
    }
}

3. List View와 Navigator

Navigation Stack과 List를 활용해 Navigation Link를 순서대로 담는다. Navigation Link를 클릭하면 그에 대한 subpage가 나타난다.

struct FirstListPage: View {
    var body: some View {
        NavigationStack {
            List {
                
                NavigationLink {
                    Text("First Subpage")
                } label: {
                    Text("First")
                }
                
                NavigationLink {
                    Text("Second Subpage")
                } label: {
                    Text("Second")
                }
                
                NavigationLink {
                    Text("Third Subpage")
                } label: {
                    Text("Third")
                }
                
                NavigationLink {
                    Text("Fourth Subpage")
                } label: {
                    Text("Fourth")
                }
            }
            .navigationTitle("Received")
        }
    }
}

이렇게 생성한 List Page를 불러오기 위해 메인 화면의 Received 부분의 내용을 다음과 같이 변경한다.

FirstListPage().tabItem {
	Label("Received", systemImage: "tray.and.arrow.down.fill")
	}

완성

위 링크에서 구현한 화면의 결과물을 확인해보자.

profile
컴퓨터공학 & 미디어콘텐츠, AI/ML, HCI, PM, QA

0개의 댓글