You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

130 lines
3.4 KiB

  1. //
  2. import Foundation
  3. import UIKit
  4. @IBDesignable
  5. class CustomPageControl: UIControl {
  6. //MARK:- Properties
  7. private var numberOfDots = [UIView]() {
  8. didSet{
  9. if numberOfDots.count == numberOfPages {
  10. setupViews()
  11. }
  12. }
  13. }
  14. @IBInspectable var numberOfPages: Int = 0 {
  15. didSet{
  16. for tag in 0 ..< numberOfPages {
  17. let dot = getDotView()
  18. dot.tag = tag
  19. dot.backgroundColor = pageIndicatorTintColor
  20. self.numberOfDots.append(dot)
  21. }
  22. }
  23. }
  24. var currentPage: Int = 0 {
  25. didSet{
  26. onPageControlSwipe()
  27. }
  28. }
  29. @IBInspectable var pageIndicatorTintColor: UIColor? = .blue
  30. @IBInspectable var currentPageIndicatorTintColor: UIColor? = .green
  31. private lazy var stackView = UIStackView.init(frame: self.bounds)
  32. private lazy var constantSpace = ((stackView.spacing) * CGFloat(numberOfPages - 1) + ((self.bounds.height * 0.45) * CGFloat(numberOfPages)) - self.bounds.width)
  33. override var bounds: CGRect {
  34. didSet{
  35. self.numberOfDots.forEach { (dot) in
  36. self.setupDotAppearance(dot: dot)
  37. }
  38. }
  39. }
  40. //MARK:- Intialisers
  41. convenience init() {
  42. self.init(frame: .zero)
  43. }
  44. init(withNoOfPages pages: Int) {
  45. self.numberOfPages = pages
  46. self.currentPage = 0
  47. super.init(frame: .zero)
  48. setupViews()
  49. }
  50. override init(frame: CGRect) {
  51. super.init(frame: frame)
  52. setupViews()
  53. }
  54. required init?(coder aDecoder: NSCoder) {
  55. super.init(coder: aDecoder)
  56. }
  57. private func setupViews() {
  58. self.numberOfDots.forEach { (dot) in
  59. self.stackView.addArrangedSubview(dot)
  60. }
  61. stackView.alignment = .center
  62. stackView.axis = .horizontal
  63. stackView.distribution = .fillEqually
  64. stackView.spacing = 8
  65. stackView.translatesAutoresizingMaskIntoConstraints = false
  66. self.addSubview(stackView)
  67. self.addConstraints([
  68. stackView.centerXAnchor.constraint(equalTo: self.centerXAnchor),
  69. stackView.centerYAnchor.constraint(equalTo: self.centerYAnchor),
  70. stackView.heightAnchor.constraint(equalTo: self.heightAnchor),
  71. ])
  72. self.numberOfDots.forEach { dot in
  73. self.addConstraints([
  74. dot.centerYAnchor.constraint(equalTo: self.stackView.centerYAnchor),
  75. dot.widthAnchor.constraint(equalToConstant: 7),
  76. dot.heightAnchor.constraint(equalToConstant: 7),
  77. ])
  78. }
  79. self.numberOfDots.forEach { dot in
  80. dot.layer.cornerRadius = dot.bounds.height / 2
  81. }
  82. }
  83. @objc private func onPageControlSwipe() {
  84. _ = numberOfDots.map { (dot) in
  85. setupDotAppearance(dot: dot)
  86. if dot.tag == currentPage {
  87. UIView.animate(withDuration: 0.2, animations: {
  88. dot.layer.cornerRadius = dot.bounds.height / 5
  89. dot.transform = CGAffineTransform.init(scaleX: 2, y: 1)
  90. dot.backgroundColor = self.currentPageIndicatorTintColor
  91. })
  92. }
  93. }
  94. }
  95. //MARK: Helper methods...
  96. private func getDotView() -> UIView {
  97. let dot = UIView()
  98. dot.translatesAutoresizingMaskIntoConstraints = false
  99. self.setupDotAppearance(dot: dot)
  100. return dot
  101. }
  102. private func setupDotAppearance(dot: UIView) {
  103. dot.transform = .identity
  104. dot.layer.cornerRadius = dot.bounds.height / 2
  105. dot.layer.masksToBounds = true
  106. dot.backgroundColor = pageIndicatorTintColor
  107. }
  108. }