[SwiftUI] Animation(Transition)이 포함된 Launch Screen 구현하기

📌 Launch Screen: 뽀대나는 앱을 위해

Launch Screen, 즉 시작 화면은 사용자가 앱을 구동했을 때 가장 먼저 마주치는 화면이다.
시작 화면이 시각적으로 매력적이라면 사용자에게 더 큰 만족감을 선사할 수도 있지만, 만약 시작 화면이 따로 없는 그저 흰 화면으로 로딩이 된다면 앱에 대한 신뢰도를 처음부터 잃어버릴 수도 있는 것이다.

그렇기 때문에 시작 화면은 사소한 것 같지만 절대 사소하지 않으며, 필수불가결하다고 볼 수 있다.

그럼 오늘은, 멋드러진 시작 화면을 위해 SwiftUI에서 그라데이션 배경이 들어간 시작 화면Animation을 포함시켜 만들어보도록 하자.

💻 시작 화면 구현

Gradient

먼저 화면의 배경색을 설정해주어야 하는데, 지난 포스팅: 그라데이션 배경 구현하기 에서 작성했던 코드를 사용할 것이다.

LinearGradient(gradient: Gradient(colors: [Color("PrimaryColor"), Color("SubPrimaryColor")]),
                            startPoint: .top, endPoint: .bottom)
            .edgesIgnoringSafeArea(.all)

View for Launch Screen

다음은, Launch Screen로 쓰일 View를 만들 것이다.

extension ContentView {
    
    var launchScreenView: some View {
        
        ZStack(alignment: .center) {
            
            LinearGradient(gradient: Gradient(colors: [Color("PrimaryColor"), Color("SubPrimaryColor")]),
                            startPoint: .top, endPoint: .bottom)
            .edgesIgnoringSafeArea(.all)
            
            Image("LaunchScreenImage")
            
        }
        
    }
    
}

앱의 시작지점인 ContentView 밑에 새로운 extension을 하나 만들어주고, 미리 Asset에 넣어 놓은 Image를 배경색 위에 덮어서 View를 구성했다.

이제 ContentView에서 Bool 타입 변수와 if 문을 이용해 시작 화면을 띄워보자.

struct ContentView: View {
    
    @State var isLoading: Bool = true
    
    var body: some View {
        
        ZStack {
            
            // 앱 화면
            Text("Launch Screen Demo").font(.largeTitle)
            
            // Launch Screen
            if isLoading {
                launchScreenView
            }
            
        }
        .onAppear {
            DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
                isLoading.toggle()
            })
        }
        
    }
}

앱은 다음과 같은 순서로 렌더링된다.

  1. 앱이 실행되면, isLoading 변수의 초기값은 true 이다.
  2. ZStack을 통해 화면에 Text(...), 그 위에 if문을 통과한 LaunchScreen이 덮인다.
  3. ZStack이 렌더링되면서, .onAppear {...} 가 실행된다.
  4. 현재부터 2초 뒤에, isLoading 변수의 값이 변경된다. (false로)
  5. 변수값이 변경되어 if문이 false가 되며, 원래 앱 화면 위에 덮여 있던 Launch Screen이 사라진다.

빌드 결과는 다음과 같다.


Animation

여기서, 조금 더 뽀대를 내보기 위해 간단한 Animation을 넣어보자.

ContentView의 코드를 아래와 같이 수정한다.

struct ContentView: View {
    
    @State var isLoading: Bool = true
    
    var body: some View {
        
        ZStack {
            
            // 1) CHANGED: zIndex added
            // 앱 화면
            Text("Launch Screen Demo\n: with Animation").font(.largeTitle).zIndex(0)
            
            // Launch Screen
            if isLoading {
            	// 2) CHANGED: transition and zIndex added
                launchScreenView.transition(.opacity).zIndex(1)
            }
            
        }
        .onAppear {
            DispatchQueue.main.asyncAfter(deadline: .now() + 2, execute: {
            	3) CHANGED: withAnimation added
                withAnimation { isLoading.toggle() }
            })
        }
        
    }
}

1) zIndex()는, ZStack에서 하위 View들을 자동으로 정확하게 인식하지 못해 Animation이 적용되지 않는 사례를 막기 위한 것이다.

2) launchScreenView 가 없어지는 지점에 .transition(.opacity) 를 추가한다.

3) isLoading 변수값을 토글하는 지점을 withAnimation { } 로 묶어준다.

위와 같이 고치게 되면, 다음과 같이 서서히 사라지는 Animation이 적용된 시작 화면을 확인할 수 있다.


📌 마치며

Animation을 적용하는 방법과 종류는 위의 방법 말고도 아주 다양하지만, 이번 포스팅에서는 수많은 방법 중 서서히 사라지는 .trasition(.opacity) 를 사용해서 구현해보았다.

개인적으로, Frontend 개발자의 실력은 적절하고 사용자 친화적인 Animation 구현에서 결정된다고 생각한다.

공부는 끝이 없으니... 노력하고 또 노력해보자!

printf("Thank You!\n");
printf("Posted by Thirsty Developer\n");

좋은 웹페이지 즐겨찾기