iOS Dev 36: Getting Started with Animations | Swift 5, XCode 13
top
제약조건 변수화constraint
값 변경 애니메이션 효과 적용private func springAnimateView() {
UIView.animate(withDuration: 1.0,
delay: 0,
usingSpringWithDamping: 0.6,
initialSpringVelocity: 0.4,
options: []) { [weak self] in
guard let self = self else { return }
if self.isActive {
self.topConstraint?.constant = 20
} else {
self.topConstraint?.constant = -(self.animationView.frame.origin.y) - self.animationView.frame.height
}
self.view.layoutIfNeeded()
} completion: { _ in
print("Animation Completed")
}
}
withDuration
은 해당 애니메이션이 얼마 동안 일어나는지, delay
는 해당 애니메이션이 얼마 뒤에 일어나는지 설정usingSpringWithDamping
은 0에 가까울 수록 세게 튕기는 댐핑 효과가 적용되고, 1에 가까울 수록 튕기지 않음initialSpringVelocity
는 프로퍼티의 이름처럼 처음에 튀어오르는 속도를 결정한다. 값이 0에 가까울 수록 빠름import UIKit
class ViewController: UIViewController {
private let animationView: UIView = {
let view = UIView()
view.layer.masksToBounds = true
view.layer.cornerRadius = 12
view.backgroundColor = .systemGreen
return view
}()
private let label: UILabel = {
let label = UILabel()
label.font = .preferredFont(forTextStyle: .title1)
label.textColor = .white
label.text = "Simple Animation"
return label
}()
private let animateButton: UIButton = {
let button = UIButton()
var config = UIButton.Configuration.filled()
config.title = "Animate"
config.baseBackgroundColor = .systemBlue
config.baseForegroundColor = .white
config.titleAlignment = .center
button.configuration = config
return button
}()
private var topConstraint: NSLayoutConstraint?
private var isActive = true
override func viewDidLoad() {
super.viewDidLoad()
setUI()
}
private func setUI() {
view.backgroundColor = .systemBackground
animationView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(animationView)
topConstraint = animationView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 10)
guard let topConstraint = topConstraint else { return }
let viewConstraints = [
topConstraint,
animationView.centerXAnchor.constraint(equalTo: view.centerXAnchor),
animationView.widthAnchor.constraint(equalToConstant: view.frame.width - view.safeAreaInsets.left - view.safeAreaInsets.right - 20),
animationView.heightAnchor.constraint(equalToConstant: 50)
]
NSLayoutConstraint.activate(viewConstraints)
animationView.addSubview(label)
label.translatesAutoresizingMaskIntoConstraints = false
let labelConstraints = [
label.centerXAnchor.constraint(equalTo: animationView.centerXAnchor),
label.centerYAnchor.constraint(equalTo: animationView.centerYAnchor)
]
NSLayoutConstraint.activate(labelConstraints)
animateButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(animateButton)
let buttonConstraints = [
animateButton.centerXAnchor.constraint(equalTo: view.centerXAnchor),
animateButton.centerYAnchor.constraint(equalTo: view.centerYAnchor)
]
NSLayoutConstraint.activate(buttonConstraints)
animateButton.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)
}
@objc private func didTapButton() {
isActive.toggle()
springAnimateView()
}
private func animateView() {
UIView.animate(withDuration: 0.5) { [weak self] in
guard let self = self else { return }
if self.isActive {
self.topConstraint?.constant = 20
} else {
self.topConstraint?.constant = -(self.animationView.frame.origin.y) - self.animationView.frame.height
}
self.view.layoutIfNeeded()
}
}
private func springAnimateView() {
UIView.animate(withDuration: 1.0,
delay: 0,
usingSpringWithDamping: 0.6,
initialSpringVelocity: 0.4,
options: []) { [weak self] in
guard let self = self else { return }
if self.isActive {
self.topConstraint?.constant = 20
} else {
self.topConstraint?.constant = -(self.animationView.frame.origin.y) - self.animationView.frame.height
}
self.view.layoutIfNeeded()
} completion: { _ in
print("Animation Completed")
}
}
}
topConstraint
만을 별도로 할당해서 저장constraint
를 직접 변경 가능, 이 이벤트가 애니메이션 효과 내부에서 발생하기 때문에 곧 애니메이션이 일어나는 것SwiftUI의 애니메이션과 UIKit의 애니메이션 역시 내부 구조는 상동하다. 즉 모두 익숙해질 수 있도록 노력하자! 애니메이션이야말로 가장 어려운 태스크 가운데 하나이지 않을까?