// // SPPlayerProgressView.swift // Thimra // // Created by 曾觉新 on 2025/4/9. // import UIKit class SPPlayerProgressView: UIView { ///滑动开始 var panStart: (() -> Void)? ///滑动中 var panChange: ((_ progress: CGFloat) -> Void)? ///滑动完成回调 var panFinish: ((_ progress: CGFloat) -> Void)? var progress: CGFloat = 0 { didSet { if !isPaning { setNeedsDisplay() } } } ///用来记录滑动时的当前进度 private var tempProgress: CGFloat = 0 ///滑动进度 private var panProgress: CGFloat = 0 var progressColor: UIColor = .color3D4556() var currentProgress: UIColor = .colorFFFFFF() var lineWidth: CGFloat = 2 ///是否在滑动中 private var isPaning: Bool = false override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = .clear let pan = UIPanGestureRecognizer(target: self, action: #selector(handlePanGesture(sender:))) self.addGestureRecognizer(pan) let tap = UITapGestureRecognizer(target: self, action: #selector(handleTapGesture(sender:))) self.addGestureRecognizer(tap) } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) { super.traitCollectionDidChange(previousTraitCollection) setNeedsDisplay() } override func draw(_ rect: CGRect) { super.draw(rect) guard let context = UIGraphicsGetCurrentContext() else { return } let width = rect.width let height = rect.height var progress = self.progress if self.isPaning { progress = self.panProgress } ///绘制进度 let progressPath = UIBezierPath(roundedRect: CGRect(x: 0, y: height - lineWidth, width: width, height: lineWidth), cornerRadius: lineWidth / 2) context.addPath(progressPath.cgPath) context.setFillColor(progressColor.cgColor) context.fillPath() ///绘制当前进度 let currentPath = UIBezierPath(roundedRect: CGRect(x: 0, y: height - lineWidth, width: width * progress, height: lineWidth), cornerRadius: lineWidth / 2) context.addPath(currentPath.cgPath) context.setFillColor(currentProgress.cgColor) context.fillPath() } } extension SPPlayerProgressView { @objc func handlePanGesture(sender: UIPanGestureRecognizer) { switch sender.state { case .began: self.isPaning = true self.tempProgress = self.progress sender.setTranslation(CGPoint(x: 0, y: 0), in: self) self.panStart?() case .changed: let point = sender.translation(in: self) let offsetX = point.x / self.width self.panProgress = self.tempProgress + offsetX if self.panProgress < 0 { self.panProgress = 0 } self.panChange?(self.panProgress) setNeedsDisplay() default: self.isPaning = false self.panFinish?(self.panProgress) self.panProgress = 0 } } @objc func handleTapGesture(sender: UITapGestureRecognizer) { let point = sender.location(in: self) let offsetX = point.x / self.width self.panFinish?(offsetX) } }