返回
AVPlayer带缓冲的进度条及全屏模式
IOS
2024-01-05 09:55:20
项目工程:
import UIKit
import AVFoundation
class ViewController: UIViewController {
private var player: AVPlayer!
private var playerLayer: AVPlayerLayer!
private var progressView: UIProgressView!
private var playButton: UIButton!
private var fullScreenButton: UIButton!
private var timeLabel: UILabel!
private var isFullScreen = false
override func viewDidLoad() {
super.viewDidLoad()
setupPlayer()
setupUI()
configureGestures()
}
private func setupPlayer() {
let videoURL = Bundle.main.url(forResource: "video", withExtension: "mp4")!
player = AVPlayer(url: videoURL)
playerLayer = AVPlayerLayer(player: player)
playerLayer.frame = view.bounds
view.layer.addSublayer(playerLayer)
player.addObserver(self, forKeyPath: "currentItem.loadedTimeRanges", options: [], context: nil)
player.addPeriodicTimeObserver(forInterval: CMTime(value: 1, timescale: 2), queue: DispatchQueue.main, using: { [weak self] time in
self?.updateProgressView(time: time)
})
}
private func setupUI() {
progressView = UIProgressView()
progressView.progressViewStyle = .default
progressView.tintColor = .red
progressView.frame = CGRect(x: 0, y: view.bounds.height - 40, width: view.bounds.width, height: 2)
view.addSubview(progressView)
playButton = UIButton(type: .system)
playButton.setImage(UIImage(systemName: "play.fill"), for: .normal)
playButton.addTarget(self, action: #selector(playPause), for: .touchUpInside)
playButton.frame = CGRect(x: (view.bounds.width - 50) / 2, y: view.bounds.height - 100, width: 50, height: 50)
view.addSubview(playButton)
fullScreenButton = UIButton(type: .system)
fullScreenButton.setImage(UIImage(systemName: "arrowshape.turn.up.right"), for: .normal)
fullScreenButton.addTarget(self, action: #selector(toggleFullScreen), for: .touchUpInside)
fullScreenButton.frame = CGRect(x: view.bounds.width - 50, y: view.bounds.height - 100, width: 50, height: 50)
view.addSubview(fullScreenButton)
timeLabel = UILabel()
timeLabel.text = "00:00/00:00"
timeLabel.textAlignment = .center
timeLabel.textColor = .white
timeLabel.frame = CGRect(x: 0, y: view.bounds.height - 60, width: view.bounds.width, height: 20)
view.addSubview(timeLabel)
}
private func configureGestures() {
let panGesture = UIPanGestureRecognizer(target: self, action: #selector(panGesture))
view.addGestureRecognizer(panGesture)
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey: Any]?, context: UnsafeMutableRawPointer?) {
if keyPath == "currentItem.loadedTimeRanges" {
updateProgressView(time: player.currentTime())
}
}
private func updateProgressView(time: CMTime) {
if let loadedTimeRanges = player.currentItem?.loadedTimeRanges, !loadedTimeRanges.isEmpty {
let timeRange = loadedTimeRanges[0]
let start = CMTimeGetSeconds(timeRange.start)
let end = CMTimeGetSeconds(timeRange.end)
let loadedDuration = end - start
progressView.progress = Float(loadedDuration / CMTimeGetSeconds(player.currentItem!.duration))
}
}
@objc private func playPause() {
if player.isPlaying {
player.pause()
playButton.setImage(UIImage(systemName: "play.fill"), for: .normal)
} else {
player.play()
playButton.setImage(UIImage(systemName: "pause.fill"), for: .normal)
}
}
@objc private func toggleFullScreen() {
isFullScreen = !isFullScreen
if isFullScreen {
let screen = UIScreen.main
let bounds = screen.bounds
let frame = CGRect(x: bounds.origin.x, y: bounds.origin.y, width: bounds.width, height: bounds.height)
playerLayer.frame = frame
self.view.frame = frame
} else {
let frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height)
playerLayer.frame = frame
self.view.frame = frame
}
}
@objc private func panGesture(gesture: UIPanGestureRecognizer) {
let translation = gesture.translation(in: view)
if translation.x > 0 {
player.seek(to: player.currentTime() + CMTime(seconds: 5, preferredTimescale: 1))
} else if translation.x < 0 {
player.seek(to: player.currentTime() - CMTime(seconds: 5, preferredTimescale: 1))
}
}
}
项目效果图:
教程:
- 导入AVFoundation框架。
- 创建AVPlayer对象并设置播放URL。
- 创建AVPlayerLayer对象并将其添加到视频播放视图中。
- 添加KVO观察者来更新进度条。
- 添加周期性时间观察者来更新当前播放时间和总时间。
- 创建进度条、播放/暂停按钮、全屏按钮和时间标签。
- 添加手势识别器来实现视频快进/快退。
- 实现全屏播放功能。
总结:
本文介绍了如何使用AVPlayer构建一个自定义的视频播放器,该播放器具有带缓冲显示的进度条、可调节播放进度的播放条,以及显示当前播放时间和总时间的标签。此外,还实现了全屏播放功能。