JXSegmentedIndicatorGradientView.swift 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. //
  2. // JXSegmentedIndicatorGradientView.swift
  3. // JXSegmentedView
  4. //
  5. // Created by jiaxin on 2019/1/16.
  6. // Copyright © 2019 jiaxin. All rights reserved.
  7. //
  8. import UIKit
  9. open class JXSegmentedIndicatorGradientView: JXSegmentedIndicatorBaseView {
  10. /// 渐变colors
  11. open var gradientColors = [CGColor]()
  12. /// 宽度增量,背景指示器一般要比cell宽一些
  13. open var gradientViewWidthIncrement: CGFloat = 20
  14. /// 渐变CAGradientLayer,通过它设置startPoint、endPoint等其他属性
  15. open var gradientLayer: CAGradientLayer {
  16. return layer as! CAGradientLayer
  17. }
  18. public let gradientMaskLayer: CAShapeLayer = CAShapeLayer()
  19. open class override var layerClass: AnyClass {
  20. return CAGradientLayer.self
  21. }
  22. private var gradientMaskLayerFrame = CGRect.zero
  23. open override func commonInit() {
  24. super.commonInit()
  25. indicatorHeight = 26
  26. gradientColors = [UIColor(red: 194.0/255, green: 229.0/255, blue: 156.0/255, alpha: 1).cgColor, UIColor(red: 100.0/255, green: 179.0/255, blue: 244.0/255, alpha: 1).cgColor]
  27. gradientLayer.startPoint = CGPoint(x: 0, y: 0)
  28. gradientLayer.endPoint = CGPoint(x: 1, y: 0)
  29. layer.mask = gradientMaskLayer
  30. }
  31. open override func refreshIndicatorState(model: JXSegmentedIndicatorParamsModel) {
  32. super.refreshIndicatorState(model: model)
  33. gradientLayer.colors = gradientColors
  34. let width = getIndicatorWidth(itemFrame: model.currentSelectedItemFrame)
  35. let height = getIndicatorHeight(itemFrame: model.currentSelectedItemFrame)
  36. let x = model.currentSelectedItemFrame.origin.x + (model.currentSelectedItemFrame.size.width - width)/2
  37. let y = (model.currentSelectedItemFrame.size.height - height)/2
  38. gradientMaskLayerFrame = CGRect(x: x, y: y, width: width, height: height)
  39. let path = UIBezierPath(roundedRect: gradientMaskLayerFrame, cornerRadius: getIndicatorCornerRadius(itemFrame: model.currentSelectedItemFrame))
  40. CATransaction.begin()
  41. CATransaction.setDisableActions(true)
  42. gradientMaskLayer.path = path.cgPath
  43. CATransaction.commit()
  44. frame = CGRect(x: 0, y: 0, width: model.contentSize.width, height: model.contentSize.height)
  45. }
  46. open override func contentScrollViewDidScroll(model: JXSegmentedIndicatorParamsModel) {
  47. super.contentScrollViewDidScroll(model: model)
  48. if model.percent == 0 || !isScrollEnabled {
  49. //model.percent等于0时不需要处理,会调用selectItem(model: JXSegmentedIndicatorParamsModel)方法处理
  50. //isScrollEnabled为false不需要处理
  51. return
  52. }
  53. let rightItemFrame = model.rightItemFrame
  54. let leftItemFrame = model.leftItemFrame
  55. let percent = model.percent
  56. var targetWidth = getIndicatorWidth(itemFrame: leftItemFrame)
  57. let leftWidth = targetWidth
  58. let rightWidth = getIndicatorWidth(itemFrame: rightItemFrame)
  59. let leftX = leftItemFrame.origin.x + (leftItemFrame.size.width - leftWidth)/2
  60. let rightX = rightItemFrame.origin.x + (rightItemFrame.size.width - rightWidth)/2
  61. let targetX = JXSegmentedViewTool.interpolate(from: leftX, to: rightX, percent: CGFloat(percent))
  62. if indicatorWidth == JXSegmentedViewAutomaticDimension {
  63. targetWidth = JXSegmentedViewTool.interpolate(from: leftWidth, to: rightWidth, percent: CGFloat(percent))
  64. }
  65. gradientMaskLayerFrame.origin.x = targetX
  66. gradientMaskLayerFrame.size.width = targetWidth
  67. let path = UIBezierPath(roundedRect: gradientMaskLayerFrame, cornerRadius: getIndicatorCornerRadius(itemFrame: leftItemFrame))
  68. CATransaction.begin()
  69. CATransaction.setDisableActions(true)
  70. gradientMaskLayer.path = path.cgPath
  71. CATransaction.commit()
  72. }
  73. open override func selectItem(model: JXSegmentedIndicatorParamsModel) {
  74. super.selectItem(model: model)
  75. let width = getIndicatorWidth(itemFrame: model.currentSelectedItemFrame)
  76. var toFrame = gradientMaskLayerFrame
  77. toFrame.origin.x = model.currentSelectedItemFrame.origin.x + (model.currentSelectedItemFrame.size.width - width)/2
  78. toFrame.size.width = width
  79. let path = UIBezierPath(roundedRect: toFrame, cornerRadius: getIndicatorCornerRadius(itemFrame: model.currentSelectedItemFrame))
  80. if isScrollEnabled && (model.selectedType == .click || model.selectedType == .code) {
  81. //允许滚动且选中类型是点击或代码选中,才进行动画过渡
  82. gradientMaskLayer.removeAnimation(forKey: "path")
  83. let animation = CABasicAnimation(keyPath: "path")
  84. animation.fromValue = gradientMaskLayer.path
  85. animation.toValue = path.cgPath
  86. animation.duration = scrollAnimationDuration
  87. animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
  88. gradientMaskLayer.add(animation, forKey: "path")
  89. gradientMaskLayer.path = path.cgPath
  90. }else {
  91. CATransaction.begin()
  92. CATransaction.setDisableActions(true)
  93. gradientMaskLayer.path = path.cgPath
  94. CATransaction.commit()
  95. }
  96. }
  97. open override func getIndicatorWidth(itemFrame: CGRect) -> CGFloat {
  98. return super.getIndicatorWidth(itemFrame: itemFrame) + gradientViewWidthIncrement
  99. }
  100. }