JXSegmentedIndicatorTriangleView.swift 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. //
  2. // JXSegmentedIndicatorTriangleView.swift
  3. // JXSegmentedView
  4. //
  5. // Created by jiaxin on 2018/12/28.
  6. // Copyright © 2018 jiaxin. All rights reserved.
  7. //
  8. import UIKit
  9. open class JXSegmentedIndicatorTriangleView: JXSegmentedIndicatorBaseView {
  10. open override class var layerClass: AnyClass {
  11. return CAShapeLayer.self
  12. }
  13. private var path = UIBezierPath()
  14. open override func commonInit() {
  15. super.commonInit()
  16. indicatorWidth = 14
  17. indicatorHeight = 10
  18. }
  19. open override func refreshIndicatorState(model: JXSegmentedIndicatorSelectedParams) {
  20. super.refreshIndicatorState(model: model)
  21. backgroundColor = nil
  22. let shapeLayer = self.layer as! CAShapeLayer
  23. shapeLayer.fillColor = indicatorColor.cgColor
  24. let width = getIndicatorWidth(itemFrame: model.currentSelectedItemFrame, itemContentWidth: model.currentItemContentWidth)
  25. let height = getIndicatorHeight(itemFrame: model.currentSelectedItemFrame)
  26. let x = model.currentSelectedItemFrame.origin.x + (model.currentSelectedItemFrame.size.width - width)/2
  27. var y: CGFloat = 0
  28. switch indicatorPosition {
  29. case .top:
  30. y = verticalOffset
  31. case .bottom:
  32. y = model.currentSelectedItemFrame.size.height - height - verticalOffset
  33. case .center:
  34. y = (model.currentSelectedItemFrame.size.height - height)/2 + verticalOffset
  35. }
  36. frame = CGRect(x: x, y: y, width: width, height: height)
  37. path = UIBezierPath()
  38. if indicatorPosition == .bottom {
  39. path.move(to: CGPoint(x: 0, y: height))
  40. path.addLine(to: CGPoint(x: width/2, y: 0))
  41. path.addLine(to: CGPoint(x: width, y: height))
  42. }else {
  43. path.move(to: CGPoint(x: 0, y: 0))
  44. path.addLine(to: CGPoint(x: width/2, y: height))
  45. path.addLine(to: CGPoint(x: width, y: 0))
  46. }
  47. path.close()
  48. shapeLayer.path = path.cgPath
  49. }
  50. open override func contentScrollViewDidScroll(model: JXSegmentedIndicatorTransitionParams) {
  51. super.contentScrollViewDidScroll(model: model)
  52. guard canHandleTransition(model: model) else {
  53. return
  54. }
  55. let rightItemFrame = model.rightItemFrame
  56. let leftItemFrame = model.leftItemFrame
  57. let percent = model.percent
  58. let targetWidth = getIndicatorWidth(itemFrame: model.leftItemFrame, itemContentWidth: model.leftItemContentWidth)
  59. let leftX = leftItemFrame.origin.x + (leftItemFrame.size.width - targetWidth)/2
  60. let rightX = rightItemFrame.origin.x + (rightItemFrame.size.width - targetWidth)/2
  61. let targetX = JXSegmentedViewTool.interpolate(from: leftX, to: rightX, percent: CGFloat(percent))
  62. self.frame.origin.x = targetX
  63. }
  64. open override func selectItem(model: JXSegmentedIndicatorSelectedParams) {
  65. super.selectItem(model: model)
  66. let targetWidth = getIndicatorWidth(itemFrame: model.currentSelectedItemFrame, itemContentWidth: model.currentItemContentWidth)
  67. var toFrame = self.frame
  68. toFrame.origin.x = model.currentSelectedItemFrame.origin.x + (model.currentSelectedItemFrame.size.width - targetWidth)/2
  69. if canSelectedWithAnimation(model: model) {
  70. UIView.animate(withDuration: scrollAnimationDuration, delay: 0, options: .curveEaseOut, animations: {
  71. self.frame = toFrame
  72. }) { (_) in
  73. }
  74. }else {
  75. frame = toFrame
  76. }
  77. }
  78. }