MoviaBox/ShortPlay/Class/Player/View/SPPlayerProgressView.swift
2025-04-09 18:24:58 +08:00

126 lines
3.5 KiB
Swift

//
// SPPlayerProgressView.swift
// ShortPlay
//
// 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 = .red
var currentProgress: UIColor = .white
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)
}
}