使用Swift開發一個貝樂虎啓蒙App - 視頻播放(二)

這是我參與8月更文挑戰的第9天,活動詳情查看:8月更文挑戰markdown

前言

上一篇咱們把視頻播放作好了,如今咱們就來作控制層。那咱們須要哪些控制功能呢?
ide

一、上下滑動屏幕左側能夠設置亮度
二、上下滑動屏幕右側能夠設置音量
三、左右滑動屏幕視頻能夠快進/快退
四、單擊屏幕隱藏/顯示上、下、右邊的view
五、雙擊屏幕暫停/播放視頻
post

WechatIMG171.jpeg

控制功能

一、先在PlayerViewController裏面增長一個PanDirection枚舉,用來標識滑動方向

enum PanDirection {
    case unkonw /// 未知
    case horizontal /// 橫向移動
    case vertical /// 縱向移動
}
複製代碼

二、給player.view添加單擊和雙擊手勢

let singleTap = UITapGestureRecognizer(target: self, action: #selector(handleSingleTap))
singleTap.delegate = self
singleTap.numberOfTapsRequired = 1
player.view.addGestureRecognizer(singleTap)

let doubleTap = UITapGestureRecognizer(target: self, action: #selector(handleDoubleTap))
doubleTap.delegate = self
doubleTap.numberOfTapsRequired = 2
player.view.addGestureRecognizer(doubleTap)

/// 解決點擊當前view時候響應其餘控件事件
singleTap.delaysTouchesBegan = true
doubleTap.delaysTouchesBegan = true
/// 雙擊失敗響應單擊事件
singleTap.require(toFail: doubleTap)

/// 單擊
@objc private func handleSingleTap() {

}

/// 雙擊
@objc private func handleDoubleTap() {
    switch player.playbackState {
        case .stopped:
            player.playFromBeginning()
        case .paused:
            player.playFromCurrentTime()
        case .playing:
            player.pause()
        case .failed:
            player.pause()
    }
}
複製代碼

三、當視頻播放成功的時候添加UIPanGestureRecognizer手勢

func playerReady(_ player: Player) {
    let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(panDirection(_:)))
    panRecognizer.delegate = self
    panRecognizer.maximumNumberOfTouches = 1
    panRecognizer.delaysTouchesBegan = true
    panRecognizer.delaysTouchesEnded = true
    panRecognizer.cancelsTouchesInView = true
    player.view.addGestureRecognizer(panRecognizer)
}

@objc private func panDirection(_ pan: UIPanGestureRecognizer) {

    /// 根據在view上Pan的位置,肯定是調音量仍是亮度
    let locationPoint = pan.location(in: player.view)
    /// 咱們要響應水平移動和垂直移動
    /// 根據上次和本次移動的位置,算出一個速率的point
    let veloctyPoint = pan.velocity(in: player.view)

    /// 判斷是垂直移動仍是水平移動
    switch pan.state {
    case .began:
        /// 使用絕對值來判斷移動的方向
        let x = abs(veloctyPoint.x)
        let y = abs(veloctyPoint.y)
        if x > y { /// 水平移動
            panDirection = .horizontal
            sumTime = Double(player.currentTimeInterval)
            isPlaying = player.playbackState == .playing
            player.pause()
            isDragged = true
        } else {
            panDirection = .vertical
            /// 開始滑動的時候,狀態改成正在控制音量
            if (locationPoint.x > player.view.bounds.size.width / 2) {
                self.isVolume = true;
            } else { /// 狀態改成顯示亮度調節
                self.isVolume = false;
            }
        }
    case .changed:
        switch panDirection {
        case .horizontal:
            horizontalMoved(value: veloctyPoint.x)
        case .vertical:
            verticalMoved(value: veloctyPoint.y) /// 垂直移動方法只要y方向的值
        default:
            break
        }
    case .ended:
        switch panDirection {
        case .horizontal:
            if isPlaying {
                player.playFromCurrentTime()
                isPlaying = false
            }
            isDragged = false
            sumTime = 0
        case .vertical:
            /// 垂直移動結束後,把狀態改成再也不控制音量
            isVolume = false
        default:
            break
        }
    default:
        break
    }
}

/// pan垂直移動的方法,設置音量/亮度
private func verticalMoved(value: CGFloat) {
    isVolume ? (volumeViewSlider?.value -= Float(value / 10000)) : (UIScreen.main.brightness -= value / 10000)
}

/// pan水平移動的方法,快進/快退
private func horizontalMoved(value: CGFloat) {
    /// 每次滑動須要疊加時間
    sumTime += Double(value) / 300
    /// 須要限定sumTime的範圍
    let totalTime = player.maximumDuration
    if sumTime > totalTime { sumTime = totalTime }
    if sumTime < 0 { sumTime = 0 }
    player.seek(to: CMTime(seconds: sumTime, preferredTimescale: CMTimeScale(1 * NSEC_PER_SEC)))
}

extension PlayerViewController: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldReceive touch: UITouch) -> Bool {
        guard let v = touch.view else { return false }
        if v.isKind(of: UISlider.self) {
            return false
        }
        if v.isKind(of: UIButton.self) {
            return false
        }
        return true
    }
}
複製代碼

設置音量以前要獲取MPVolumeView裏面的UISlider來控制音量ui

let volumeView = MPVolumeView()
volumeViewSlider = nil
for v in volumeView.subviews {
    if v.classForCoder.description() == "MPVolumeSlider", let slider = v as? UISlider {
        volumeViewSlider = slider
    }
}

do {
    /// 使用這個category的應用不會隨着手機靜音鍵打開而靜音,可在手機靜音下播放聲音
    try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category.playback)
} catch {}
複製代碼

下面是效果展現。手機錄屏錄時,設置屏幕亮度在錄完視頻裏面是沒有效果的 視頻播放1.gifspa

相關文章
相關標籤/搜索