Created
December 7, 2020 08:30
-
-
Save mcfans/393e94622c19da7742ff07ed490c2378 to your computer and use it in GitHub Desktop.
UIView Animate Gradient
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class GradientView: UIView { | |
var color: UIColor | |
init(_ color: UIColor) { | |
self.color = color | |
super.init(frame: .zero) | |
} | |
required init?(coder: NSCoder) { | |
fatalError("init(coder:) has not been implemented") | |
} | |
var middleAlpha: CGFloat { | |
get { | |
if let layer = layer as? UIViewAnimatableGradientLayer { | |
return layer.middleAlpha | |
} | |
return 0 | |
} | |
set { | |
if let layer = layer as? UIViewAnimatableGradientLayer { | |
layer.middleAlpha = newValue | |
// Change model layer property | |
layer.colors = [ | |
color.withAlphaComponent(0).cgColor, | |
color.withAlphaComponent(newValue).cgColor, | |
color.cgColor, | |
] | |
} | |
} | |
} | |
override class var layerClass: AnyClass { | |
UIViewAnimatableGradientLayer.self | |
} | |
} | |
class UIViewAnimatableGradientLayer: CAGradientLayer { | |
@NSManaged var middleAlpha: CGFloat | |
override init() { | |
super.init() | |
} | |
override init(layer: Any) { | |
super.init(layer: layer) | |
if let layer = layer as? UIViewAnimatableGradientLayer { | |
self.middleAlpha = layer.middleAlpha | |
} | |
} | |
required init?(coder: NSCoder) { | |
super.init(coder: coder) | |
} | |
private class func isCustomAnimKey(key: String) -> Bool { | |
return key == "middleAlpha" | |
} | |
override class func needsDisplay(forKey key: String) -> Bool { | |
if self.isCustomAnimKey(key: key) { | |
return true | |
} else { | |
return super.needsDisplay(forKey: key) | |
} | |
} | |
override func action(forKey event: String) -> CAAction? { | |
if UIViewAnimatableGradientLayer.isCustomAnimKey(key: event) { | |
// Use a normal animatable property name to retrieve a CABasicAnimation, we need timing curve and duration info from it. | |
if let infoAction = super.action(forKey: "backgroundColor") as? CABasicAnimation { | |
infoAction.keyPath = "colors" | |
if let pLayer = presentation() { | |
infoAction.fromValue = pLayer.colors | |
} | |
infoAction.toValue = nil | |
return infoAction | |
} | |
setNeedsDisplay() | |
return nil | |
} | |
return super.action(forKey: event) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment