[iOS] Animation

Lena·2021년 2월 7일
0

iOS에서 애니메이션을 사용할 수 있는 방법은 크게 2가지

  • UIKit, UIView API ✔️
  • Core Animation API

UIView.animate

  • Closure 기반
  • 애니메이션이 동작하는 동안 user interface disable
UIView.animate(withDuration: 0.5,
               delay: 0.4,
               options: [.curveEaseOut],
               animations: { [weak self] in
                 self?.view.layoutIfNeeded()
      }, completion: nil)
  • options: UIView.AnimationOptions

    • .allowUserInteraction : 애니메이션 중에 user interface를 활성화
    • .repeat : 애니메이션 무한 반복
    • .curveEaseInOut : 빨라졌다가 다시 느려지는 애니메이션 옵션
    • .curveEaseIn : 점점 빨라짐
    • .curveEaseOut : 점점 느려짐
    • .transitionFlipFromLeft : 왼쪽에서부터 뒤집히는 애니메이션
    • .transition~ 시작하는 옵션들은 UIView.transition() 으로 호출해야 한다.
  • 애니메이션이 가능한 뷰 속성(animatable property)

    • frame, bounds, center, transform, background, alpha
    • layoutSubviews() 없이 애니메이션 효과가 나타나는, 뷰의 built-in animation 속성들을 의미한다.

View Life Cycle

view의 라이프 사이클을 돌면서 적절하게 animate 함수를 실행한다.

  • viewDidLoad : view가 메모리에 올라온 상태 —prepareAnimation()
  • viewWillAppear : prepareAnimation()
  • viewDidAppear : view가 스크린에 나타난 뒤에 호출, 이 때 애니메이션을 실행 — showAnimation()
func prepareAnimation() {
    nameLabelCenterX.constant -= self.view.bound.width
}

func showAnimation() {
    nameLabelCenterX.constant = 0 // constraint 변경해도 레이아웃을 업데이트하지 않으면 애니메이션 효과가 보이지 않음

    UIView.animate(withDuration: 0.5,
                   delay: 0.3,
                   usingSpringWithDamping: 0.6, // 0 ~ 1.0, 0에 가까울수록 세게
                   initialSpringVelocity: 1.0, // 0 ~ 1.0,  0에 가까울수록 빠르게
                   options: .allowUserInteraction,
                   animations: { self.view.layoutIfNeeded() },
                   completion: nil)
    
    UIView.transition(with: imageView,
                      duration: 0.3,
                      options: .transitionFlipFromLeft,
                      animations: nil,
                      completion: nil)
}

layoutIfNeeded

UIView의 instance method
Lays out the subviews immediately, if layout updates are pending.

layoutIfNeeded는 subview의 레이아웃을 즉시 갱신한다. = layoutSubviews() 호출

layoutSubviews

  • 서브뷰의 레이아웃을 즉시 업데이트 시켜주는 메소드
  • 호출되면 해당 뷰의 모든 서브뷰들이 layoutSubViews()를 연달아 호출한다.
  • 따라서 비용이 많이 드는 메서드. 직접 호출하는 것이 지양된다.
  • 이 메소드는 시스템에 의해서 뷰의 값이 다시 계산되어야 하는 시점(update cycle)에 자동으로 호출된다. ✔️
  • layoutSubviews를 유도할 수 있는 여러 방법이 존재한다(일종의 layoutSubviews() 호출을 예약하는 행위). ✔️✔️
  • layoutSubviews()가 호출되고나면 viewDidLayoutSubviews()가 호출된다.

The update cycle is the point at which control returns to the main run loop after the app finishes running all your event handling code.

아래와 같이 뷰의 레이아웃이 변경될 경우, update cycle에 레이아웃이 업데이트될 수 있도록 시스템이 자동으로 뷰의 업데이트를 예약한다.

  • 뷰의 크기를 변경하거나
  • 뷰에 서브뷰를 추가하거나
  • 사용자가 스크롤뷰를 스크롤 하거나
  • 디바이스를 회전시키거나
  • 뷰의 오토레이아웃 constraint 값을 변경시켰을 때

시스템이 자동으로 뷰의 업데이트를 예약하는 것 말고, 수동으로 예약하는 방법도 있다.

  • setNeedsLayout()
  • layoutIfNeeded()

setNeedsLayout

비용이 가장 적게 드는 방법.
이 메서드를 호출한 뷰는 재계산되어야 하는 뷰라고 수동으로 체크되며, update cycle에 layoutSubviews() 호출한다.

layoutIfNeeded

setNeedsLayout과 마찬가지로 수동으로 layoutSubviews를 예약하는 메서드지만,
차이점은 update cycle이 돌 때까지 기다리지 않고 즉시 layoutSubviews()를 호출한다.


https://jinnify.tistory.com/66
https://developer.apple.com/documentation/uikit/uiview/animationoptions
https://baked-corn.tistory.com/105

0개의 댓글