App Icon, Launch Screen, and Launch Animation | SwiftUI Crypto App #24
var body: some Scene {
WindowGroup {
ZStack {
NavigationView {
HomeView()
.toolbar(.hidden)
}
.environmentObject(viewModel)
ZStack {
if showLaunchView {
LaunchView(showLaunchView: $showLaunchView)
.transition(.move(edge: .leading))
}
}
.zIndex(2.0)
}
}
}
HomeView
가 해당 앱의 메인 뷰LaunchView
를 상단에 띄우기showLaunchView
를 통해 현재 런치 뷰가 메인 뷰 위에 있을 경우를 체크import SwiftUI
@main
struct CryptoAppBootCampApp: App {
@StateObject private var viewModel = HomeViewModel()
@State private var showLaunchView: Bool = true
init() {
UINavigationBar.appearance().largeTitleTextAttributes = [.foregroundColor: UIColor(Color.theme.accent)]
UINavigationBar.appearance().titleTextAttributes = [.foregroundColor: UIColor(Color.theme.accent)]
}
var body: some Scene {
WindowGroup {
ZStack {
NavigationView {
HomeView()
.toolbar(.hidden)
}
.environmentObject(viewModel)
ZStack {
if showLaunchView {
LaunchView(showLaunchView: $showLaunchView)
.transition(.move(edge: .leading))
}
}
.zIndex(2.0)
}
}
}
}
zIndex
를 통해 상단에 있음을 보장 가능showLaunchView
를 @State
로 선언, 바인딩 프로퍼티로 넘겨줌으로써 런치 뷰 상의 핸들링을 현 시점의 뷰에서 확인 가능import SwiftUI
struct LaunchView: View {
@State private var loadingText: [String] = "Loading your portfolio...".map({String($0)})
@State private var showLoadingText: Bool = false
private let timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
@State private var counter: Int = 0
@State private var loops: Int = 0
@Binding var showLaunchView: Bool
var body: some View {
ZStack {
Color.launch.background
.ignoresSafeArea()
Image("logo-transparent")
.resizable()
.frame(width: 100, height: 100)
ZStack {
if showLoadingText {
HStack(spacing: 0) {
ForEach(0..<loadingText.count) { index in
Text(loadingText[index])
.font(.headline)
.fontWeight(.heavy)
.foregroundColor(Color.launch.accent)
.offset(y: counter == index ? -5 : 0)
}
}
.transition(AnyTransition.scale.animation(.easeIn))
}
}
.offset(y: 70)
}
.onAppear {
showLoadingText.toggle()
}
.onReceive(timer) { _ in
withAnimation(.spring()) {
let lastIndex = loadingText.count - 1
if counter == lastIndex {
counter = 0
loops += 1
if loops >= 2 {
showLaunchView = false
}
} else {
counter += 1
}
}
}
}
}
showLoadingText
를 onAppear
에서 값 변경함으로써 애니메이션 스케일 효과 적용loadingText
로 적용할 문자열 데이터를 배열로 관리, 전체적인 Hstack을 통해 각 텍스트 별 핸들링 가능timer
와 counter
, loops
를 통해 현재 주어진 loadingText
의 어떤 문구를 offset 변경을 통해 애니메이션 효과를 줄지 확인 가능loops
가 특정 횟수가 될 때 바인딩으로 받고 있는 showLaunchView
변경, 메인 뷰 시점에서 현재 런치 뷰를 내리고 홈 뷰로 진입 가능커스텀 런치 뷰를 통해 메인 뷰로 들어가기 전 런치 스크린과 같은 효과를 만들 수 있다! 즉 원하는 애니메이션 기법 등을 보다 유연하게 적용할 수 있다는 점이 장점이다.