Skip to content

Instantly share code, notes, and snippets.

@eliperkins
Created November 6, 2018 22:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save eliperkins/b603a6cda7bea83cb6a8b254af23cfb4 to your computer and use it in GitHub Desktop.
Save eliperkins/b603a6cda7bea83cb6a8b254af23cfb4 to your computer and use it in GitHub Desktop.
lol gradients in UIKit πŸ™ƒπŸ™ƒπŸ™ƒ
import UIKit
@objc(CLBLinearGradientView)
class LinearGradientView: UIView {
@objc var layerBacked: Bool {
didSet {
switch (layerBacked, layerView) {
case (true, .none): addLayerView()
case (false, .some): removeLayerView()
default: break
}
}
}
@objc var colors: [UIColor] {
didSet {
layerView?.colors = colors
setNeedsDisplay()
}
}
@objc var locations: [CGFloat] {
didSet {
layerView?.locations = locations
setNeedsDisplay()
}
}
override init(frame: CGRect) {
self.layerBacked = true
self.colors = [.clear, .clear]
self.locations = [0, 1]
super.init(frame: frame)
addLayerView()
backgroundColor = .clear
isOpaque = false
}
private var layerView: LayerBackedGradientView?
private func addLayerView() {
let layerView = LayerBackedGradientView()
layerView.colors = colors
layerView.locations = locations
self.layerView = layerView
addSubview(layerView)
}
private func removeLayerView() {
layerView?.removeFromSuperview()
layerView = nil
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
layerView?.frame = bounds
}
override func draw(_ rect: CGRect) {
if layerBacked {
super.draw(rect)
} else {
guard let context = UIGraphicsGetCurrentContext() else { return }
let colorSpace = CGColorSpaceCreateDeviceRGB()
let cgColors = colors.map({ $0.cgColor })
let cfColors = cgColors as CFArray
guard let gradient = CGGradient(colorsSpace: colorSpace, colors: cfColors, locations: locations) else { return }
let end = CGPoint(x: 0, y: rect.maxY)
context.drawLinearGradient(gradient, start: .zero, end: end, options: [])
}
}
}
fileprivate class LayerBackedGradientView: UIView {
var colors: [UIColor] {
didSet {
gradientLayer.colors = colors.map({ $0.cgColor })
}
}
var locations: [CGFloat] {
didSet {
gradientLayer.locations = locations as [NSNumber]
}
}
private var gradientLayer: CAGradientLayer! {
return self.layer as? CAGradientLayer
}
override init(frame: CGRect) {
self.colors = [.clear, .clear]
self.locations = [0, 1]
super.init(frame: frame)
backgroundColor = .clear
gradientLayer.colors = colors.map({ $0.cgColor })
gradientLayer.locations = locations as [NSNumber]
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override class var layerClass: AnyClass {
return CAGradientLayer.self
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment