Created
November 6, 2018 22:42
-
-
Save eliperkins/b603a6cda7bea83cb6a8b254af23cfb4 to your computer and use it in GitHub Desktop.
lol gradients in UIKit πππ
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
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