Blame view

HDFwear/Basic/View/ProgressButton.swift 5.08 KB
f2cf74c7   yangbin   1.0.20(4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
  //
  //  ProgressButton.swift
  //  Twear
  //
  //  Created by yangbin on 2021/12/29.
  //
  
  import Foundation
  import UIKit
  
  fileprivate let StartAngle = CGFloat(Double.pi / 2)
  
  //protocol ProgressButtonDelegate: NSObjectProtocol {
  //    func progressFinished()
  //}
  
  public class ProgressButton: UIButton {
      // 延迟初始化背景层采用 fill 来绘层背景
      private lazy var bgLayer: CAShapeLayer = CAShapeLayer()
      // 延迟初始化进度条层采用 stroke 来绘制边框
      private lazy var progressLayer: CAShapeLayer = CAShapeLayer()
      // 进度条百分比最小为 0.0最大为 1.0
      private var progress: Double = 0
      
      private let percent: CGFloat = 1.0/20.0
      // 延迟初始化标签文本内容
  //    private lazy var label: UILabel = UILabel(frame: CGRect.zero)
      var progressClosure: (() -> ())?
      public override init(frame: CGRect) {
          super.init(frame: frame)
          initView()
      }
      
      required init?(coder: NSCoder) {
          super.init(coder: coder)
          initView()
      }
      
      // 仅初始化 layer & label以及颜色后续再给定实际大小和约束
      func initView() {
          // fillColor   用于背景颜色填充
          // strokeColor 用于线条颜色
  
          self.addTarget(self, action: #selector(touchDown(_:)), for: .touchDown)
          self.addTarget(self, action: #selector(touchCancel(_:)), for: [.touchDragExit, .touchDragOutside, .touchUpInside])
  //        self.addTarget(self, action: #selector(touchFinish(_:)), for: .touchUpInside)
          // 0.25 透明度的白色背景
          bgLayer.fillColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0).cgColor
          layer.addSublayer(bgLayer)
          
          // 边框全白边框宽度为 4
          progressLayer = CAShapeLayer()
          progressLayer.fillColor = nil
          progressLayer.strokeColor = UIColor(red: 1, green: 1, blue: 1, alpha: 1).cgColor
          progressLayer.lineWidth = 4.0
          layer.addSublayer(progressLayer)
          
          // 标签字体颜色为纯白
  //        label.textColor = UIColor(red: 1, green: 1, blue: 1, alpha: 1)
  //        // 使用约束来布局
  //        label.translatesAutoresizingMaskIntoConstraints = false
  //        addSubview(label)
      }
      
      public override func draw(_ rect: CGRect) {
          super.draw(rect)
         
          
      }
      
      @objc func touchDown(_ sender: UIButton) {
          progressLayer.strokeEnd = 0
          GCDTimer.shared.scheduledDispatchTimer(WithTimerName: "ProgressButton", timeInterval: 0.1, queue: .main, repeats: true) { [weak self] in
              self?.startTimer()
          }
      }
      @objc func touchCancel(_ sender: Any) {
          progressLayer.strokeEnd = 0
          cancelTimer()
      }
      
      private func cancelTimer() {
          if GCDTimer.shared.isExistTimer(WithTimerName: "ProgressButton") {
              GCDTimer.shared.cancleTimer(WithTimerName: "ProgressButton")
          }
      }
      
      func startTimer() {
          if progressLayer.strokeEnd >= 1 {
              cancelTimer()
              progressLayer.removeFromSuperlayer()
              progressClosure?()
          } else {
              progressLayer.strokeEnd += percent
          }
      }
      
      // 布局 resize 时会触发该方法
      public override func layoutSubviews() {
          super.layoutSubviews()
          let radius = bounds.height / 2 - 2
          bgLayer.path = UIBezierPath(roundedRect: bounds, cornerRadius: radius).cgPath
  
          // 设置 start  12点钟方向开始默认是3点钟方向
          // end = 360 * progress - start
          // 设置为 顺时针 方向
          let end = CGFloat(Double.pi * 2) - StartAngle
          progressLayer.path = UIBezierPath(arcCenter: CGPoint(rect: bounds), radius: radius,
                                            startAngle: -StartAngle, endAngle: end,
                                            clockwise: true).cgPath
          progressLayer.strokeEnd = 0
          // 因为  = 所以圆角为宽 or 高的一半即可
          
          // 设置 label 的中心点 = self 的中心点
  //        NSLayoutConstraint.activate([
  //            label.centerXAnchor.constraint(equalTo: self.centerXAnchor),
  //            label.centerYAnchor.constraint(equalTo: self.centerYAnchor)
  //        ])
      }
      deinit {
          print("deinit\(NSStringFromClass(type(of: self)))!!!!!!!")
      }
      
      public func setProgress(_ progress: Double) {
          // 进度条目标值 0.0 -> progress
  //        self.progress = progress
          // 初始化 label
  //        label.text = "\(duration)s"
          progressLayer.strokeEnd = 0.5
          // 创建进度条动画时长 = duration
  //        if !animated {
  //            let animation = CABasicAnimation(keyPath: "strokeEnd")
  //            animation.duration = 1
  //            animation.fromValue = 0
  //            animation.toValue = 1
  //            progressLayer.add(animation, forKey: nil)
  //        }
      }
      
  //    public func setContent(_ text: String) {
  //        label.text = "\(text)s"
  //    }
  }
  
  extension CGPoint {
      // 扩展 rect 的中心点
      init(rect: CGRect) {
          self.init(x: rect.width / 2, y: rect.height / 2)
      }
  }