在Swift中为AVPlayer添加自定义控件

17

我试图创建一个表格视图,以便我能够播放视频。我可以使用AVPlayer和layer实现这一点。

我想在视频视图底部添加一个自定义的播放和暂停按钮以及一个滑动条。

AVPlayerController内置了这些控件。

如何在AVPlayer中实现这些控件?我一直在寻找示例,但我没有找到任何内容。

有没有GitHub示例或代码样本可以供我参考?任何帮助都将不胜感激。


你看过苹果的示例代码了吗?https://developer.apple.com/library/content/samplecode/AVPlayerDemo/Introduction/Intro.html - Lepidopteron
你需要隐藏自定义控件并创建自己的控件。 - Anbu.Karthik
我正在寻找Swift的示例。 - A.S
2个回答

50

这里我添加了一些要点,您需要根据自己的需求进行定制。

步骤1

首先隐藏您的AVPlayer控件,

 YourAVPlayerViewController.showsPlaybackControls = false

步骤-2

创建如下结构:

enter image description here

一个当前持续时间的标签,一个总持续时间的标签,一个用于播放和暂停当前播放器的UIButton,以及一个用于寻找视频的UISlider。

步骤-3

最初关闭简单步骤。

首先使用按钮操作停止和播放播放器,currentPlayer是您的AVPlayer名称。

@IBAction func handlePlayPauseButtonPressed(_ sender: UIButton) {
   //  sender.isSelected ?  currentPlayer.pause() :   currentPlayer.play()
    if sender.isSelected {
        currentPlayer.pause()
    }
    else {
        currentPlayer.play()
    }
}

第二步是设置视频时长,就像这样

    let duration : CMTime = currentPlayer.currentItem!.asset.duration
    let seconds : Float64 = CMTimeGetSeconds(duration)

    lblOverallDuration.text = self.stringFromTimeInterval(interval: seconds)
第三步将播放器当前时间设置为当前时长标签。
    let duration : CMTime = currentPlayer.currentTime()
    let seconds : Float64 = CMTimeGetSeconds(duration)

    lblcurrentText.text = self.stringFromTimeInterval(interval: seconds)
以下方法是将NSTimeInterval转换为HH:MM:SS。
func stringFromTimeInterval(interval: TimeInterval) -> String {

    let interval = Int(interval)
    let seconds = interval % 60
    let minutes = (interval / 60) % 60
    let hours = (interval / 3600)
    return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
}

最后,我们使用滑块控件来计算搜索时间

_playheadSlider.addTarget(self, action: #selector(self.handlePlayheadSliderTouchBegin), for: .touchDown)
_playheadSlider.addTarget(self, action:    #selector(self.handlePlayheadSliderTouchEnd), for: .touchUpInside)
_playheadSlider.addTarget(self, action: #selector(self.handlePlayheadSliderTouchEnd), for: .touchUpOutside)
_playheadSlider.addTarget(self, action: #selector(self.handlePlayheadSliderValueChanged), for: .valueChanged)

让我们开始行动吧,当触摸开始时停止播放器。

handlePlayheadSliderTouchBegin

@IBAction func handlePlayheadSliderTouchBegin(_ sender: UISlider) {
currentPlayer.pause()
}
设置当前项目标签以计算sender.value * CMTimeGetSeconds(currentPlayer.currentItem.duration)
@IBAction func handlePlayheadSliderValueChanged(_ sender: UISlider) {

        let duration : CMTime = currentPlayer.currentItem!.asset.duration
     let seconds : Float64 = CMTimeGetSeconds(duration) * sender.value
 //   var newCurrentTime: TimeInterval = sender.value * CMTimeGetSeconds(currentPlayer.currentItem.duration)
lblcurrentText.text = self.stringFromTimeInterval(interval: seconds)
   }

最后根据查找结果移动玩家

 @IBAction func handlePlayheadSliderTouchEnd(_ sender: UISlider) {

  let duration : CMTime = currentPlayer.currentItem!.asset.duration
var newCurrentTime: TimeInterval = sender.value * CMTimeGetSeconds(duration)
var seekToTime: CMTime = CMTimeMakeWithSeconds(newCurrentTime, 600)
currentPlayer.seek(toTime: seekToTime)
}

2
非常详细的答案 :) - Siu Chung Chan
3
如何进入全屏模式? - Bhavin Ramani
@BhavinRamani - 根据问题,我添加了答案,如果您需要全屏,需要添加一个按钮,并在动作内使用transform rotate。 - Anbu.Karthik
@Anbu.karthik,你如何在AVPlayer上添加自定义视图? - Syed Ali Salman
1
UISlider在播放视频时未更新,这是一个bug,因此答案不完整。请相应地更新答案。 - iPhone 7
显示剩余4条评论

1
除了Anbu.Karthik的回答之外,滑块处理可以在一个单独的函数中更好地处理,如下所示:
slider.addTarget(self, action: #selector(self.handlePlayheadSliderValueChanged(sender:event:)), for: .valueChanged)

滑块值更改:

注意switch case处理滑块事件的所有阶段

@objc func handlePlayheadSliderValueChanged(sender: UISlider, event: UIEvent) {
    if let duration: CMTime = player?.currentItem?.asset.duration {
        let newCurrentTime: Float64 = CMTimeGetSeconds(duration) * Double(sender.value)
        videoLengthLabel.text = self.stringFromTimeInterval(interval: newCurrentTime)
        if let touchEvent = event.allTouches?.first {
            switch (touchEvent.phase) {
            case .began:
                // on slider touch begin
                pauseVideo()
                break
            case .moved:
                // on slider movement
                let seekToTime: CMTime = CMTimeMakeWithSeconds(newCurrentTime, preferredTimescale: 600)
                player?.seek(to: seekToTime, completionHandler: { (completedSeek) in
                    // any additional operation upon seek completion
                })
                break
            case .ended:
                // on slider touch end (finger lift)
                playVideo()
                break
            default:
                break
            }
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接