使用Swift开发一个贝乐虎启蒙App – 视频播放(三)

这是我参与8月更文挑战的第10天,活动详情查看:8月更文挑战

前言

上一篇我们把视频播放的控制层做好了,现在我们把上、下、右边的View和锁屏的做出来

WechatIMG171.jpeg

创建View

1、新建一个PlayerTopView,然后创建返回TV锁屏按钮,具体创建这里就不展示了,主要展示一下,点击屏幕隐藏PlayerTopView

暴露一个isShow属性,方便外面设置

var isShow: Bool = false {
    didSet {
        if isShow {
            UIView.animate(withDuration: 0.25, animations: {
                self.transform = CGAffineTransform(translationX: 0, y: -50.fit)
                self.alpha = 0
            }) { _ in}
        } else {
            transform = CGAffineTransform(translationX: 0, y: -50.fit)
            UIView.animate(withDuration: 0.25) {
                self.alpha = 1
                self.transform = .identity
            }
        }
    }
}
复制代码

2、新建一个PlayerBottomView

进度条这块我就用系统的UISlider,不去自定义了。布局就不展示了

/// 点击暂停/播放按钮
var playerHandler: () -> Void = {}
/// 点击播放循环按钮 0列表循环播放 1单曲循环
var cycleHandler: (Int) -> Void = { _ in }
/// 拖动进度条
var sliderValueDidChange: (Double) -> Void = { _ in }
/// 进度条按下/松开状态
var sliderTouch: (SliderTouch) -> Void = { _ in }

/// 是否在播放
var isPlaying: Bool = false {
    didSet {
        playBtn.isSelected = isPlaying
    }
}

var isShow: Bool = false {
    didSet {
        if isShow {
            UIView.animate(withDuration: 0.25, animations: {
                self.transform = CGAffineTransform(translationX: 0, y: 50.fit)
                self.alpha = 0
            }) {_ in}
        } else {
            transform = CGAffineTransform(translationX: 0, y: 50.fit)
            UIView.animate(withDuration: 0.25) {
                self.alpha = 1
                self.transform = .identity
            }
        }
    }
}

/// 缓冲进度条进度值
var progressValue: Float = 0 {
    didSet {
        progressView.progress = progressValue
    }
}

/// 进度条进度值
var sliderValue: Float = 0 {
    didSet {
        slider.setValue(sliderValue, animated: true)
    }
}
复制代码

3、新建一个PlayerRightView

右侧的就用UITableView来做,布局就不展示了

/// 选择的item
var didSelectedItem: (Int) -> Void = { _ in }

var isShow: Bool = false {
    didSet {
        if isShow {
            UIView.animate(withDuration: 0.25, animations: {
                self.transform = CGAffineTransform(translationX: 170.fit, y: 0)
                self.alpha = 0
            }) {_ in}
        } else {
            transform = CGAffineTransform(translationX: 170.fit, y: 0)
            UIView.animate(withDuration: 0.25) {
                self.alpha = 1
                self.transform = .identity
            }
        }
    }
}

/// 列表数据
var items: [RecChildDataItemsModel] = [] {
    didSet {
        tableView.reloadData()
    }
}
复制代码

4、锁屏View

锁屏状态下是不能操作的,所以新建一个PlayerLockView,然后PlayerLockView加在keyWindow上面

class PlayerLockView: UIView {
    /// 解锁回调
    private var didUnlock: () -> Void = {}

    /// 解锁view,添加一个长按手势
    private lazy var lockImageView: UIImageView = {
        let view = UIImageView()
        view.isUserInteractionEnabled = true
        view.image = "video_btn_longUnlock".image
        let gesture = UILongPressGestureRecognizer(target: self, action: #selector(gestureAction(_:)))
        gesture.minimumPressDuration = 3
        view.addGestureRecognizer(gesture)
        return view
    }()

    override init(frame: CGRect) {
        super.init(frame: frame)

        backgroundColor = UIColor.clear
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    class func show(_ unlock: @escaping () -> Void) {
        let view = PlayerLockView(frame: UIScreen.main.bounds)
        view.didUnlock = unlock
        view.addSubviews()
    }

    private func addSubviews() {
        UIApplication.shared.keyWindow?.addSubview(self)
        addSubview(lockImageView)
        
        lockImageView.snp.makeConstraints { (make) in
            make.left.top.equalToSuperview()
            make.size.equalTo(CGSize(width: 50, height: 50))
        }
    }
    
    @objc private func gestureAction(_ longPress: UILongPressGestureRecognizer) {
        self.didUnlock()
        self.removeFromSuperview()
    }
}
复制代码

使用

1、在PlayerViewController里面懒加载一个PlayerTopView

private lazy var topView: PlayerTopView = { PlayerTopView() }()

/// 返回
topView.didClose = { [weak self] in
    guard let `self` = self else { return }
    self.goBack()
}

/// 锁屏
topView.didLock = { [weak self] in
    guard let `self` = self else { return }
    self.bottomView.isShow = true
    self.topView.isShow = true
    self.rightView.isShow = true
    PlayerLockView.show { [weak self] in
        guard let `self` = self else { return }
        self.bottomView.isShow = false
        self.topView.isShow = false
        self.rightView.isShow = false
    }
}
复制代码

2、在PlayerViewController里面懒加载一个PlayerBottomView

private lazy var bottomView: PlayerBottomView = { PlayerBottomView() }()

/// 点击播放按钮设置暂停/播放
bottomView.playerHandler = { [weak self] in
    guard let `self` = self else { return }
    self.playerBtnClick()
}

/// 列表循环/单曲循环
bottomView.cycleHandler = { [weak self] value in
    guard let `self` = self else { return }
    self.isSingle = value == 1
}

/// 快进/快退
bottomView.sliderValueDidChange = { [weak self] value in
    guard let `self` = self else { return }
    let sliderTime = value * self.player.maximumDuration
    self.player.seek(to: CMTime(seconds: sliderTime, preferredTimescale: CMTimeScale(1 * NSEC_PER_SEC)))
}

/// 按下slider,当按下时暂停播放,松开时播放
bottomView.sliderTouch = { [weak self] status in
    guard let `self` = self else { return }
    if status == .down {
        self.isPlaying = self.player.playbackState == .playing
        self.isDragged = true
        self.player.pause()
    }
    if status == .up {
        if self.isPlaying {
            self.player.playFromCurrentTime()
            self.isPlaying = false
        }
        self.isDragged = false
    }
}

/// 点击播放按钮设置暂停/播放
@objc private func playerBtnClick() {
    switch player.playbackState {
    case .stopped:
        player.playFromBeginning()
    case .playing:
        player.pause()
    case .paused:
        player.playFromCurrentTime()
    default:
        player.playFromBeginning()
    }
}
复制代码

3、在PlayerViewController里面懒加载一个PlayerRightView

private lazy var rightView: PlayerRightView = {
    let view = PlayerRightView()
    view.didSelectedItem = { [weak self] index in
        guard let `self` = self else { return }
        self.playerIndex = index
        self.isClickPlayer = true
        self.player.stop()
    }
    return view
}()

/// 请求右侧的数据
private func requestData() {
    Network.Rec
        .videos(id: id)
        .request()
        .responseData(RecChildDataModel.self) { [weak self] (model) in
            guard let `self` = self else { return }
            self.dataSource = model.result.items
            for (index, item) in self.dataSource.enumerated() {
                if item.url == self.url {
                    self.player.url = URL(string: item.url)
                    self.dataSource[index].isSelected = true
                    self.playerIndex = index
                    continue
                }
            }
            self.rightView.items = self.dataSource
            self.player.playFromBeginning()
    } failure: { (error) in
        Toast.show(info: error.errorMessage)
    }
}

/// 每次切换动画的时候配置
private func configDataSource() {
    for (index, _) in dataSource.enumerated() {
        dataSource[index].isSelected = false
    }
    if dataSource.count - 1 >= playerIndex {
        dataSource[playerIndex].isSelected = true
        player.url = URL(string: dataSource[playerIndex].url)
    } else {
        dataSource[0].isSelected = true
        player.url = URL(string: dataSource[0].url)
    }
    rightView.items = dataSource
    player.playFromBeginning()
}
复制代码

IMG_0237.PNG

到这视频播放就结束了

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享