앱 안내 온보딩 페이지 등에서 자주 보이는 진행바를 만들어 봤다.
여기서는 shape의 너비를 변경시키는 방식이다.
애니메이션을 적용해서 부드럽게 채워진다.
// Created by Toughie on 2023/05/09.
//
import SwiftUI
struct ProgressBarView: View {
//탭뷰를 위한 상태 프로퍼티. tag에 따라 변경됨.
@State private var selectedTab: Int = 0
//selectedTab 변경에 따라 값이 바뀜 -> 진행바 너비 늘어남
@State private var progress: CGFloat = 0
let stringArray: [String] = ["안녕하세요!", "반가워요~", "준비", "시작!"]
var body: some View {
VStack {
Spacer()
ProgressBar(progress: $progress)
Spacer()
TabView(selection: $selectedTab) {
ForEach(icons.indices, id: \.self) { index in
ZStack {
Rectangle()
.foregroundColor(.gray.opacity(0.8))
Text(icons[index])
.font(.largeTitle)
.foregroundColor(.white)
}
}
}
.frame(height: UIScreen.main.bounds.height * 0.7)
//원형 인디케이터 스타일
.tabViewStyle(PageTabViewStyle(indexDisplayMode: .automatic))
//뷰가 등장하면서 첫 칸이 채워지도록 하기 위한 코드.
//없으면 진행바가 전혀 채워지지 않았다가, 탭을 넘기면 확 많이 채워짐(2개분)
.onAppear {
progress = CGFloat(selectedTab + 1) / CGFloat(icons.count)
}
//스와이프를 통해 selectedTab값이 변경되면
//해당 값을 통해 progress 값을 업데이트해줌
.onChange(of: selectedTab) { newValue in
withAnimation(.easeInOut(duration: 0.5)) {
progress = CGFloat(newValue + 1) / CGFloat(icons.count)
}
}
Spacer()
}
.padding(.horizontal)
.background(Color.black)
}
}
프로그레스바
struct ProgressBar: View {
@Binding var progress: CGFloat
var body: some View {
GeometryReader { geometry in
ZStack(alignment: .leading) {
RoundedRectangle(cornerRadius: 5)
.foregroundColor(.gray.opacity(0.3))
RoundedRectangle(cornerRadius: 5)
.frame(width: geometry.size.width * progress)
.foregroundColor(.green)
}
}
.frame(height: 10)
}
}
여기서 간단하게 GeometryReader와 ZStack 동작 방식에 대해 알아보자.
GeometryReader는 부모 뷰의 크기를 읽고 자식 뷰에게 전달하는 뷰이다.
여기서는 탭뷰가 존재하는 ProgressBarView의 바디 부분의 VStack의 사이즈가 부모 뷰인 것이다.
이 사이즈에 맞게(*available size) RoundedRectangle의 너비가 정해지는 것이다.
* available size -> 부모 뷰가 자식 뷰에게 제공하는 공간의 크기
첫번째 RoundedRectangle의 너비는 available 사이즈에 따라 결정됨. (여기서는 부모뷰의 VStack의 사이즈)
'SwiftUI > SwiftUI(examples)' 카테고리의 다른 글
모델? 뷰모델? (0) | 2023.05.13 |
---|---|
Data Essentials in SwiftUI #WWDC20 (0) | 2023.05.10 |