jane1choi / TIL

Today I Learned #심야아요

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[iOS] Lottie를 이용한 로딩 뷰 삽입

jane1choi opened this issue · comments

Lottie란?

Lottie는 Airbnb에서 개발한 JSON형태로 애니메이션을 사용할 수 있는 라이브러리입니다!
벡터 기반 애니메이션과 아트를 최소한의 코드로 실시간으로 렌더링하는 Android 및 iOS용 모바일 라이브러리로,
JSON 형식의 파일만 있다면 여러 플랫폼(Android, Web, Windows 등)에서 동일한 애니메이션을 그려낼 수 있습니다.
모바일 앱에서는 주로 splash 화면이나 loading 뷰에 많이 쓰이는 것 같습니다!

Lottie를 이용해 로딩 뷰를 만들어보자!

1. Lottie import하기

먼저 Lottie 라이브러리를 import 해야겠죠?
깃허브 공식문서(https://github.com/airbnb/lottie-ios) 에 가면 라이브러리를 import하는 방법이 나와있습니다!
저는 CocoaPods을 이용해 import 해주겠습니다!

스크린샷 2022-06-22 오후 11 03 02

공식 문서를 따라 podfile에 위의 코드를 추가해주고 pod install까지 해주면!

스크린샷 2022-06-22 오후 11 10 05

이렇게 잘 설치가 되면,

스크린샷 2022-06-22 오후 11 20 00

이렇게 Lottie를 import하여 사용할 수 있습니다!

2. JSON 파일 프로젝트 파일에 추가하기

애니메이션으로 사용할 JSON 형식의 파일을 프로젝트에 추가해서 사용합니다.
애니메이션 파일을 프로젝트 파일에 드래그 앤 드랍하여 추가할 수 있는데, 이때 주의할 점은 실제 JSON 파일이 없으면
실행되지 않을 수 있으니 Copy items if needed을 체크해주어야 합니다!

스크린샷 2022-06-22 오후 11 29 48

3. 애니메이션 실행하기

JSON 파일까지 추가했다면!!
이제 원하는 곳에서 애니메이션을 실행시켜주면 되겠죠?
Lottie를 사용하여 애니메이션을 실행시키는 방법은 아주 간단합니다!

  1. Lottie를 사용할 뷰에 대한 정의
  2. 애니메이션에 대한 액션 설정

스크린샷 2022-06-26 오후 3 14 17

스크린샷 2022-06-26 오후 3 13 02

Lottie 라이브러리 안에 있는 AnimationView를 이용해 JSON파일을 재생할 수 있는데,
위와 같이 AnimationView는 LottieView를, LottieView는 UIView를 상속받기 때문에
UIView의 속성 모두를 사용할 수 있습니다!

Lottie를 사용할 파일에

import Lottie

이렇게 Lottie를 임포트 해주고, 먼저 Lottie를 사용할 뷰에 대한 정의를 해줍니다.
(저는 BaseVC에 Lottie를 정의해두고 함수를 호출하여 원하는 뷰에서 애니메이션이 보일 수 있도록 구성했습니다)

//  BaseVC.swift

lazy var loadingView: AnimationView = {
        let animationView = AnimationView(name: "loading_lottie")
        animationView.frame = CGRect(x: 0, y: 0, width: 64, height: 64)
        animationView.contentMode = .scaleAspectFit
        animationView.loopMode = .loop
        animationView.isHidden = true
        
        return animationView
    }()
    
    lazy var checkView: AnimationView = {
        let animationView = AnimationView(name: "check_lottie")
        animationView.frame = CGRect(x: 0, y: 0, width: 64, height: 64)
        animationView.contentMode = .scaleAspectFit
        animationView.loopMode = .playOnce
        animationView.isHidden = true
        
        return animationView
    }()

저는 위와 같이 두개의 AnimationView타입의 뷰인 loadingViewcheckView를 선언해주고 여러 속성들을 추가해주었습니다!

//  BaseVC.swift

func setLottie() {
        view.addSubviews([bgView, containerView])
        containerView.addSubviews([loadingView, checkView])
        
        bgView.snp.makeConstraints {
            $0.top.bottom.leading.trailing.equalToSuperview()
        }
        
        containerView.snp.makeConstraints {
            $0.centerX.centerY.equalToSuperview()
            $0.width.height.equalTo(64)
        }
    }

그런 다음, addSubview() 메소드를 이용해서 containerView의 subView로 추가해주었습니다!

이제 애니메이션에 대한 액션을 정의해주어야 하는데, play(), pause(), stop() 메소드를 이용해서 원하는 동작을 설정할 수 있습니다!

func loadingPlay() {
        [bgView, containerView, loadingView].forEach { view in
            view.isHidden = false
        }
        loadingView.play()
    }
    
    func loadingStop() {
        loadingView.stop()
        [bgView, containerView, loadingView].forEach { view in
            view.isHidden = true
        }
    }
    
    func checkPlay(_ vc: UIViewController) {
        [bgView, containerView, checkView].forEach { view in
            view.isHidden = false
        }
        checkView.play() { _ in
            vc.dismiss(animated: true)
        }
    }
    
    func checkStop() {
        [bgView, containerView, checkView].forEach { view in
            view.isHidden = true
        }
        checkView.stop()
    }

위와 같이 원하는 동작을 함수로 정의해두고,

//  CreateUploadVC.swift

// MARK: Life Cycle
    override func viewDidLoad() {
        super.viewDidLoad()
        configUI()
        setDelegate()
        setLottie() // Lottie 추가
    }

// MARK: - Network
extension CreateUploadVC {
    private func createPost(content: String, image: UIImage) {
        loadingPlay() // loading 애니메이션 시작
        FeedAPI.shared.createPostAPI(content: content, image: image) { networkResult in
            switch networkResult {
            case .success:
                NotificationCenter.default.post(name: NSNotification.Name("completeBtnDidTap"), object: nil, userInfo: nil)
                self.loadingStop() // loading 애니메이션 멈춤
                self.checkPlay(self) // check 애니메이션 시작
            case .requestErr(let res):
                print(res)
            default:
                print("networkFail")
            }
        }
    }
}

원하는 뷰에서 호출하는 방식으로 구현해주었습니다!

구현 화면

Simulator Screen Recording - iPhone 11 - 2022-06-26 at 15 58 19