본문 바로가기

iOS

[iOS] UIView Animation으로 애니메이션 구현하는 방법

특정한 시간 동안 한 개 혹은 그 이상의 뷰들의 변화에 애니메이션을 주는 것에 대해 알아보겠습니다. 오늘은 그 중에서도 타입 메소드로 선언된 UIView.animate 를 살펴보겠습니다.

 

class func animate(withDuration duration: TimeInterval, animations: @escaping () -> Void)

 

파라미터 animations 에 원하는 속성의 최종값을 설정하면 현재값에서 최종값으로 변하는 애니메이션이 실행됩니다.

UIView가 제공하는 속성중에서 애니메이션을 지원하는 속성은 다음과 같습니다.

  • frame
  • bounds
  • center
  • transform
  • alpha
  • backgroundColor

기본적인 구현 방법은 아래와 같습니다.

 

let newFrame = CGRect(x: 0.0, y: 0.0, width: 100, height: 100)

UIView.animate(withDuration: 0.3) {
    self.sampleView.frame = newFrame
}

 

completion 블록의 파라미터로 애니메이션이 중단없이 정상적으로 종료되었다면 true 이외에는 false 가 전달됩니다.

 

let oldFrame = CGRect(x: 0.0, y: 0.0, width: 50, height: 50)
let newFrame = CGRect(x: 0.0, y: 0.0, width: 100, height: 100)

UIView.animate(withDuration: 0.3, animations: {
    self.sampleView.frame = newFrame
}, completion: { finished in
    self.sampleView.frame = oldFrame
})

 

애니메이션이 실행된 후 다시 원래상태로 돌아가는 것에도 애니메이션이 필요하다면,

 

UIView.animate(withDuration: 0.3, animations: {
    self.sampleView.frame = newFrame
}, completion: { finished in
    UIView.animate(withDuration: 0.3, animations: {
        self.sampleView.frame = oldFrame
    })
})

 

이렇게 중첩해서 구현하면 됩니다. 하지만! 중첩하여 애니메이션을 구현하게 되면 소스의 가독성이 떨어지게 되고 중첩된 애니메이션이 많아질 수록 가독성은 더 떨어지게 됩니다.

 

이 부분은 Keyframe Animation 을 이용하면 깔끔하게 구현할 수 있습니다.

 

애니메이션의 기본 curve는 .curveEaseInOut 입니다. 천천히 시작했다가 점점 빨라지다가 다시 천천히 종료가 되는 curve 입니다. options 파라미터에 원하는 옵션을 주어 애니메이션 효과를 조절할 수 있습니다.

 

UIView.animate(withDuration: 0.3, delay: 0.0, options: .curveLinear, animations, animation, completion: nil)

UIView.animate(withDuration: 0.3, delay: 0.0, options: [.curveLinear, .repeat, .autoreverse], animations, animation, completion: nil)

 

애니메이션의 옵션은 하나만 줄 수도 있고 배열로도 줄 수도 있습니다. 자세한 옵션 항목들은 AnimationOptions 에서 알아보시길 바랍니다!

 

UIView.animate는 iOS4 부터 지원해왔습니다. 오래된 API이기도 합니다. 특히 애니메이션을 종료시키고 싶을 땐 개별적으로 종료할 수는 없습니다. iOS 10부터는 Property Animator 를 제공합니다.

 

self.sampleView.layer.removeAllAnimations()

오토레이아웃을 조정하여 애니메이션 구현하기

@IBOutlet weak var widthConstraint: NSLayoutConstraint!
@IBOutlet weak var heightConstraint: NSLayoutConstraint!

 

위와 같이 제약조건 Outlet 연결이 되어있다고 하겠습니다.

 

UIView.animate(withDuration: 0.3) {
    self.widthConstraint.constant = 100
    self.widthConstraint.constant = 100
}

 

이렇게 구현하면 애니메이션 없이 크기만 딱 바뀌게 됩니다. 제약조건을 변경하면서 애니메이션을 주려면 layoutIfNeeded 를 호출해야 합니다.

 

self.widthConstraint.constant = 100
self.widthConstraint.constant = 100

UIView.animate(withDuration: 0.3) {
    self.view.layoutIfNeeded()
}

 

만약 애니메이션이 잘 작동하지 않는다면 해당 뷰에 setNeedsUpdateConstraints 를 호출하면 됩니다.

 

self.widthConstraint.constant = 100
self.widthConstraint.constant = 100
self.sampleView.setNeedsUpdateConstraints()

UIView.animate(withDuration: 0.3) {
    self.view.layoutIfNeeded()
}