목차
- CALayer란?
- CALayer 구조
- CALayer 사용 예제
UIView를 다룰 때 layer를 한 번쯤은 보셨을 겁니다.
최근에 복잡한 Custom UI를 개발해야해서 (그라디언트 + 그림자 + 애니메이션 + 모서리 둥글게)
CALayer에 대해서 학습해보았습니다.
1. CALayer란?
An object that manages image-based content and allows you to perform animations on that content.
시각적 콘텐츠 관리 및 애니메이션화를 위한 인터페이스를 제공하는 Core Animation 프레임워크의 기본 클래스
생소한 거 또 나왔다.
Core Animation 프레임워크..?
1-1. Core Animation
Core Animation is a graphics rendering and animation infrastructure available on both iOS and OS X that you use to animate the views and other visual elements of your app.
코어 애니메이션은 iOS 및 OS X 모두에서 앱의 view와 다른 시각적 요소의 애니메이션을 할 수 있는 그래픽 렌더링 및 애니메이션 인프라입니다.
iOS 앱을 작성하고 있다면 알든 모르든 Core Animation을 사용하고 있습니다.
Core Animation을 사용하면 애니메이션의 각 프레임을 그리는 데 필요한 대부분의 작업이 자동으로 수행됩니다. Core Animation이 나머지는 대부분의 실제 드로잉 작업을 온보드 그래픽 하드웨어에 넘겨 렌더링을 가속화합니다. 이 자동 그래픽 가속은 CPU에 부담을 주지 않고 앱 속도를 저하시키지 않으면서 높은 프레임 속도와 부드러운 애니메이션을 제공합니다.
(대부분의 레이어는 앱에서 실제 그리기를 수행하지 않는다고 합니다. 앱이 제공하는 콘텐츠를 비트맵에 캐싱하고 해당 레이어를 변경하면 관련된 상태 정보만 변경된다고 합니다.) <Core Animation이 컨텐츠를 그리는 방법>
저희가 주로 사용하는 High Level의 UIKit 모듈은 Low Level의 Core Animation을 사용하고 있네요.
view.backgroundColor = .blue
Apple이 추상화해준 덕분에 이렇게 간단하게 백그라운드의 색을 줄 수 있던 것이었습니다. 👍
2. CALayer 구조
Layer의 구조는 UIView의 계층구조와 비슷합니다. 하나의 Layer 안에 다른 여러 Layer가 들어갈 수 있습니다.
3. CALayer 사용 예제
3-1. 그림자 그리기
- View Shadow 관련 속성 사용하는 방법
- CALayer 만들어서 사용하는 방법
< View Shadow 관련 속성 사용하는 방법 >
- View는 Layer와 달리 터치 이벤트와 같은 이벤트를 받을 수 있습니다.
- View의 Shadow는 View의 크기에 따라 동적으로 변합니다.
< CALayer 사용하는 방법 >
CALayer를 애니메이션 하기 위해선 CABasicAnimation와 같은 코드를 추가 작성해주어야 합니다. (View와 달리 레이어는 자체 모양을 정의하지 않습니다. 레이어는 단순히 비트맵을 둘러싼 상태 정보를 관리합니다. 비트맵 자체는 뷰 드로잉 자체의 결과이거나 고정 이미지일 수 있습니다.)
- 코드 -
class ViewController: UIViewController {
let testView = UIView(frame: .init(x: 50, y: 100, width: 200, height: 200))
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(testView)
addShadow()
UIView.animate(withDuration: 8.0) { [unowned self] in
testView.frame = CGRect(x: 50, y: 100, width: 300, height: 500)
}
}
// UIView에 있는 property를 통해 사용
func addShadow() {
testView.layer.borderWidth = 2
testView.layer.borderColor = UIColor.blue.cgColor
testView.layer.shadowColor = UIColor.black.cgColor
testView.layer.shadowOpacity = 1
testView.layer.shadowOffset = CGSize(width: 10, height: 10)
testView.layer.shadowRadius = 2
}
// Layer 만들어서 사용
func addShadow() {
let shadowLayer = CAShapeLayer()
shadowLayer.frame = testView.bounds
shadowLayer.borderWidth = 2
shadowLayer.borderColor = UIColor.blue.cgColor
shadowLayer.shadowColor = UIColor.black.cgColor
shadowLayer.shadowOpacity = 1
shadowLayer.shadowOffset = CGSize(width: 10, height: 10)
shadowLayer.shadowRadius = 2
testView.layer.addSublayer(shadowLayer)
}
}
3-2. 그라디언트 그리기
class ViewController: UIViewController {
let testView = UIView(frame: .init(x: 50, y: 100, width: 200, height: 200))
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(testView)
addGradient()
}
func addGradient() {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = testView.bounds
gradientLayer.colors = [UIColor.green.cgColor, UIColor.yellow.cgColor]
gradientLayer.borderWidth = 1
gradientLayer.borderColor = UIColor.black.cgColor
testView.layer.addSublayer(gradientLayer)
}
}
3-3.Shadow Layer + Gradient Layer + Animation
class ViewController: UIViewController {
let testView = UIView(frame: .init(x: 50, y: 100, width: 200, height: 200))
override func viewDidLoad() {
super.viewDidLoad()
self.view.addSubview(testView)
addShadow()
addGradient()
}
func addShadow() {
testView.layer.shadowColor = UIColor.black.cgColor
testView.layer.shadowOpacity = 1
testView.layer.shadowOffset = CGSize(width: 10, height: 10)
testView.layer.shadowRadius = 2
}
func addGradient() {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = testView.bounds
gradientLayer.colors = [UIColor.green.cgColor, UIColor.yellow.cgColor]
gradientLayer.borderWidth = 1
gradientLayer.borderColor = UIColor.black.cgColor
testView.layer.addSublayer(gradientLayer)
let animation = CABasicAnimation(keyPath: "bounds.size.height")
animation.fromValue = gradientLayer.bounds.height
animation.toValue = gradientLayer.bounds.height * 2
animation.duration = 2.0
animation.autoreverses = true
animation.repeatCount = .infinity
gradientLayer.add(animation, forKey: "bounds.size.height")
}
}
참고
- Apple 코어 애니메이션 프로그래밍 가이드
- Apple Core Animation Doc
- Core Animation Key Path
- Apple CABasicAnimaition Doc
'IOS Swift' 카테고리의 다른 글
Xcode Cloud (2) - Work flow (0) | 2023.07.02 |
---|---|
Xcode cloud (1) - Setting (0) | 2023.06.04 |
[iOS+8] Swift JSON null 디코딩 처리 방법 (0) | 2023.04.23 |
[iOS 13+] Compositional Layout (0) | 2023.04.09 |
Apple 멤버쉽이 만료되면 발생되는 일(feat. iOS) (0) | 2023.01.25 |