내용정리
CAGradientLayer를 이용해서UIView에 그라디언트를 적용했지만,UIView.animate()를 통해 뷰의 크기가 변경될 때 그라디언트가 정상적으로 애니메이션 되지 않는 문제가 발생했다.
이를 분석하고 해결해보자
UIView의 크기를 UIView.animate(withDuration:)를 통해 변경하면, 일반적인 서브뷰들은 부드럽게 변하지만, CAGradientLayer를 적용한 경우 그라디언트의 크기가 즉시 변경되거나 갱신되지 않는 문제가 발생할 수 있다.
func updateGradient() {
guard let gradientLayer = self.layer.sublayers?.first(where: { $0 is CAGradientLayer }) as? CAGradientLayer else { return }
UIView.animate(withDuration: 0.3) {
gradientLayer.frame = self.bounds // 애니메이션이 적용되지 않음!
}
}
위의 메소드에서 기대한 결과는 그라디언트가 자연스럽게 크기 변화에 맞춰 애니메이션이 적용되는 것이지만, 실제 실행 결과는 그라디언트는 애니메이션 없이 크기가 즉시 변경된다.
CAGradientLayer는 CALayer의 하위 클래스이며, UIView.animate는 UIView의 속성(frame, bounds 등)에 대해서만 애니메이션을 적용한다.
하지만 CAGradientLayer는 애니메이션을 자동으로 적용하지 않으며, UIView.animate로도 애니메이션이 동작하지 않는다.
즉, UIView.animate를 사용해 gradientLayer.frame을 변경하더라도, CAGradientLayer의 속성 변경에는 애니메이션이 적용되지 않는다.
CAGradientLayer의 속성 변화에 애니메이션을 적용하려면 CABasicAnimation을 사용해야 한다.
// 해결 코드
func updateGradient() {
guard let gradientLayer = self.layer.sublayers?.first(where: { $0 is CAGradientLayer }) as? CAGradientLayer else { return }
let animation = CABasicAnimation(keyPath: "bounds")
animation.fromValue = gradientLayer.bounds
animation.toValue = self.bounds
animation.duration = 0.3
animation.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)
gradientLayer.add(animation, forKey: "bounds")
gradientLayer.frame = self.bounds
}
✅ UIView.animate는 UIView의 속성에 대해서만 애니메이션을 적용하며, CAGradientLayer에는 적용되지 않는다.
✅ CAGradientLayer의 크기 변경을 부드럽게 애니메이션하려면 CABasicAnimation을 사용해야 한다.
✅ bounds나 frame 속성을 CABasicAnimation을 통해 변경하면, 기대한 대로 자연스러운 애니메이션이 적용된다.
앞으로 CALayer의 애니메이션을 적용할 때는 이런 점을 잘 확인하며 진행해야겠다.
그라디언트를 넣은 뷰가 예쁜데...