GradientDesignable.swift 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146
  1. //
  2. // Created by Jake Lin on 12/4/15.
  3. // Copyright © 2015 IBAnimatable. All rights reserved.
  4. //
  5. import UIKit
  6. public protocol GradientDesignable: class {
  7. var gradientMode: GradientMode { get set }
  8. var startColor: UIColor? { get set }
  9. var endColor: UIColor? { get set }
  10. var predefinedGradient: GradientType? { get set }
  11. var startPoint: GradientStartPoint { get set }
  12. }
  13. // MARK: - UIView
  14. extension GradientDesignable where Self: UIView {
  15. public func configureGradient() {
  16. configureGradient(in: self)
  17. }
  18. }
  19. // MARK: - NavigationBar
  20. extension GradientDesignable where Self: UINavigationBar {
  21. public func configureGradient() {
  22. let navBarFrame = CGRect(x: 0, y: 0, width: bounds.width, height: UIApplication.shared.statusBarFrame.height)
  23. let gradientLayer = makeGradientLayer()
  24. gradientLayer?.frame = navBarFrame
  25. gradientLayer?.cornerRadius = layer.cornerRadius
  26. let image = gradientLayer?.makeImage()
  27. setBackgroundImage(image, for: .default)
  28. }
  29. }
  30. // MARK: - Layers
  31. extension CALayer {
  32. fileprivate func makeImage() -> UIImage? {
  33. UIGraphicsBeginImageContext(frame.size)
  34. render(in: UIGraphicsGetCurrentContext()!)
  35. let outputImage = UIGraphicsGetImageFromCurrentImageContext()
  36. UIGraphicsEndImageContext()
  37. return outputImage
  38. }
  39. }
  40. // MARK: - Common
  41. extension GradientDesignable {
  42. func configureGradient(in view: UIView) {
  43. view.subviews.filter { $0 is PrivateGradientView }.forEach {
  44. $0.removeFromSuperview()
  45. }
  46. guard let gradientLayer = makeGradientLayer() else {
  47. return
  48. }
  49. gradientLayer.cornerRadius = view.layer.cornerRadius
  50. gradientLayer.frame = view.bounds
  51. let gradientView = PrivateGradientView(frame: view.bounds, gradientLayer: gradientLayer)
  52. view.insertSubview(gradientView, at: 0)
  53. }
  54. private func makeGradientLayer() -> CALayer? {
  55. guard let colors = gradientColors() else {
  56. return nil
  57. }
  58. switch gradientMode {
  59. case .linear:
  60. return makeLinearLayer(colors: colors)
  61. case .radial:
  62. return makeRadialLayer(colors: colors)
  63. case .conical:
  64. return makeConicalLayer(colors: colors)
  65. }
  66. }
  67. private func gradientColors() -> [CGColor]? {
  68. if let startColor = startColor, let endColor = endColor {
  69. return [startColor.cgColor, endColor.cgColor]
  70. } else if let startColor = predefinedGradient?.colors.start, let endColor = predefinedGradient?.colors.end {
  71. return [startColor.cgColor, endColor.cgColor]
  72. }
  73. return nil
  74. }
  75. private func makeLinearLayer(colors: [CGColor]) -> CAGradientLayer {
  76. let layer = CAGradientLayer()
  77. layer.colors = colors
  78. layer.startPoint = startPoint.startPoint
  79. layer.endPoint = startPoint.endPoint
  80. return layer
  81. }
  82. private func makeRadialLayer(colors: [CGColor]) -> RadialGradientLayer {
  83. let layer = RadialGradientLayer()
  84. layer.colors = colors
  85. layer.startPoint = startPoint.startPoint
  86. layer.endPoint = startPoint.endPoint
  87. return layer
  88. }
  89. private func makeConicalLayer(colors: [CGColor]) -> ConicalGradientLayer {
  90. let layer = ConicalGradientLayer()
  91. layer.colors = colors
  92. layer.startPoint = startPoint.startPoint
  93. layer.endPoint = startPoint.endPoint
  94. return layer
  95. }
  96. }
  97. // MARK: - PrivateGradientView
  98. private class PrivateGradientView: UIView {
  99. init(frame: CGRect, gradientLayer: CALayer) {
  100. super.init(frame: frame)
  101. layer.insertSublayer(gradientLayer, at: 0)
  102. autoresizingMask = [.flexibleWidth, .flexibleHeight]
  103. }
  104. required init?(coder aDecoder: NSCoder) {
  105. fatalError("init(coder:) has not been implemented")
  106. }
  107. override class var layerClass: AnyClass {
  108. return CALayer.self
  109. }
  110. }