Reputation: 53
I have a problem with animating CALayer after updating to Xcode12 and iOS14 - animations that used to work on iOS13 are not working on iOS14. Here is the code for animations:
private func animateCellPress() {
let lightShadowAnimation = CABasicAnimation(keyPath: "shadowOffset")
lightShadowAnimation.fromValue = CGSize(width: -self.shadowRadius, height: -self.shadowRadius)
lightShadowAnimation.toValue = CGSize(width: self.shadowRadius, height: self.shadowRadius)
lightShadowAnimation.fillMode = .forwards;
lightShadowAnimation.isRemovedOnCompletion = false;
lightShadowAnimation.duration = self.animationDuration
self.lightShadow.add(lightShadowAnimation, forKey: lightShadowAnimation.keyPath)
let darkShadowAnimation = CABasicAnimation(keyPath: "shadowOffset")
darkShadowAnimation.fromValue = CGSize(width: self.shadowRadius, height: self.shadowRadius)
darkShadowAnimation.toValue = CGSize(width: -self.shadowRadius, height: -self.shadowRadius)
darkShadowAnimation.fillMode = .forwards;
darkShadowAnimation.isRemovedOnCompletion = false;
darkShadowAnimation.duration = self.animationDuration
self.darkShadow.add(darkShadowAnimation, forKey: darkShadowAnimation.keyPath)
}
lightShadow and darkShadow are stored as a properties and here is the initialisation code for them:
private func initializeDarkShadow() {
darkShadow = CALayer()
darkShadow.frame = bounds
darkShadow.backgroundColor = backgroundColor?.cgColor
darkShadow.cornerRadius = cornerRadius
darkShadow.shadowOffset = CGSize(width: shadowRadius, height: shadowRadius)
darkShadow.shadowOpacity = 1
darkShadow.shadowRadius = shadowRadius
darkShadow.shadowColor = Asset.Colors.darkShadow.color.cgColor
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: bounds.size)
darkShadow.shadowPath = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius).cgPath
layer.insertSublayer(darkShadow, at: 0)
}
private func initializeLightShadow() {
lightShadow = CALayer()
lightShadow.frame = bounds
lightShadow.backgroundColor = backgroundColor?.cgColor
lightShadow.cornerRadius = cornerRadius
lightShadow.shadowOffset = CGSize(width: -shadowRadius, height: -shadowRadius)
lightShadow.shadowOpacity = 1
lightShadow.shadowRadius = shadowRadius
lightShadow.shadowColor = Asset.Colors.lightShadow.color.cgColor
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: bounds.size)
lightShadow.shadowPath = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius).cgPath
layer.insertSublayer(lightShadow, at: 0)
}
Any ideas on what's wrong and how can I fix it? Also I am not getting any compiler errors or warnings. Console log is empty as well.
Upvotes: 0
Views: 1142
Reputation: 4383
This works. I think each time you are calling your animate layoutSubviews is being called thus removing the layer and the animation. You could either just update the frame there or check if the layer has already been added. If that is not the issue then there is something wrong with you press or touch function. Create a project with a single view and copy and paste this into your ViewController file.
import UIKit
class TableViewCell : UITableViewCell{
let darkShadowColor = UIColor.green
let lightShadowColor = UIColor.red
let animationDuration : Double = 2
var darkShadow = CALayer()
var lightShadow = CALayer()
let cornerRadius : CGFloat = 4
let shadowRadius : CGFloat = 3
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
initializeDarkShadow()
initializeLightShadow()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
initializeDarkShadow()
initializeLightShadow()
}
private func initializeDarkShadow() {
darkShadow = CALayer()
darkShadow.frame = bounds
darkShadow.backgroundColor = backgroundColor?.cgColor
darkShadow.cornerRadius = cornerRadius
darkShadow.shadowOffset = CGSize(width: shadowRadius, height: shadowRadius)
darkShadow.shadowOpacity = 1
darkShadow.shadowRadius = shadowRadius
darkShadow.shadowColor = darkShadowColor.cgColor
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: bounds.size)
darkShadow.shadowPath = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius).cgPath
layer.insertSublayer(darkShadow, at: 0)
}
private func initializeLightShadow() {
lightShadow = CALayer()
lightShadow.frame = bounds
lightShadow.backgroundColor = backgroundColor?.cgColor
lightShadow.cornerRadius = cornerRadius
lightShadow.shadowOffset = CGSize(width: -shadowRadius, height: -shadowRadius)
lightShadow.shadowOpacity = 1
lightShadow.shadowRadius = shadowRadius
lightShadow.shadowColor = lightShadowColor.cgColor
let rect = CGRect(origin: CGPoint(x: 0, y: 0), size: bounds.size)
lightShadow.shadowPath = UIBezierPath(roundedRect: rect, cornerRadius: cornerRadius).cgPath
layer.insertSublayer(lightShadow, at: 0)
}
func animateCellPress() {
print("called")
let lightShadowAnimation = CABasicAnimation(keyPath: "shadowOffset")
lightShadowAnimation.fromValue = CGSize(width: -self.shadowRadius, height: -self.shadowRadius)
lightShadowAnimation.toValue = CGSize(width: self.shadowRadius, height: self.shadowRadius)
lightShadowAnimation.beginTime = CACurrentMediaTime()
lightShadowAnimation.fillMode = .both;
lightShadowAnimation.isRemovedOnCompletion = false;
lightShadowAnimation.duration = self.animationDuration
self.lightShadow.add(lightShadowAnimation, forKey: nil)
let darkShadowAnimation = CABasicAnimation(keyPath: "shadowOffset")
darkShadowAnimation.fromValue = CGSize(width: self.shadowRadius, height: self.shadowRadius)
darkShadowAnimation.toValue = CGSize(width: -self.shadowRadius, height: -self.shadowRadius)
darkShadowAnimation.beginTime = CACurrentMediaTime()
darkShadowAnimation.fillMode = .both;
darkShadowAnimation.isRemovedOnCompletion = false;
darkShadowAnimation.duration = self.animationDuration
self.darkShadow.add(darkShadowAnimation, forKey: nil)
}
override func layoutSubviews() {
super.layoutSubviews()
self.lightShadow.frame = self.bounds
self.darkShadow.frame = self.bounds
}
}
class ViewController: UIViewController {
let identifier = "someCellID"
lazy var tableView : UITableView = {
let tv = UITableView(frame: self.view.bounds)
tv.delegate = self
tv.dataSource = self
tv.autoresizingMask = [.flexibleWidth,.flexibleHeight]
tv.register(TableViewCell.self, forCellReuseIdentifier: identifier)
return tv
}()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.view.addSubview(tableView)
}
}
extension ViewController : UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: identifier, for: indexPath) as? TableViewCell{
cell.selectionStyle = .none
return cell
}
print("error")
return UITableViewCell()
}
func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath) {
if let cell = tableView.cellForRow(at: indexPath) as? TableViewCell{
cell.animateCellPress()
}
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 50
}
}
Upvotes: 2