使用Swift开发一个贝乐虎启蒙App – 读绘本(二)

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

前言

上一篇我们把下载并解压就已经做好了,现在我们就开始对解压后的文件进行处理

截屏2021-08-10 11.18.52.png

读绘本其实就是一张图片配个音频,滑到哪张图片播放哪个音频,绘本信息都是在index.json文件里面,现在我们就来解析index.json文件

截屏2021-08-10 09.38.39.png

获取数据

  • 根据index.json文件里面的数据,建立绘本模型BookModel
struct BookModel: Codable {
    let audioMode: String
    let cover: String
    let name: String
    let pageCount: Int
    var pagesv2: [BookPageModel]
    let portrait: Bool
    let read: String
    let version: String
    
    /// 自定义参数-封面图片的路径
    var coverURL: String
}

struct BookPageModel: Codable {
    let audio: String
    let bac: String
    let p: Int
    let time: String
    
    /// 自定义参数-图片的路径
    var imageURL: String
    /// 自定义参数-音频的路径
    var audioURL: String
}
复制代码
  • ZipManager里面新增一个getBook获取绘本模型的方法
/// 获取绘本模型
private func getBook(_ url: String) -> BookModel? {
    guard let u = URL(string: url) else {
        return nil
    }
    /// 根据url获取获取最后一级文件夹名称
    let lastFileDocuments = u.lastPathComponent.replacingOccurrences(of: ".zip", with: "")
    let allPath = bookUnzipFilePath + url.MD5String + "/\(lastFileDocuments)/"
    /// index.json文件路径
    let indexPath = allPath + "index.json"
    do {
        let indexData = try Data(contentsOf: URL(fileURLWithPath: indexPath))
        if var bookModel = try? CleanJSONDecoder().decode(BookModel.self, from: indexData) {
            /// 设置封面图片的路径
            bookModel.coverURL = allPath + bookModel.cover
            for (index, model) in bookModel.pagesv2.enumerated() {
                /// 设置图片的路径
                bookModel.pagesv2[index].imageURL = allPath + model.bac
                /// 设置音频的路径
                bookModel.pagesv2[index].audioURL = allPath + model.audio
            }
            return bookModel
        }
        return nil
    } catch {
        return nil
    }
}
复制代码

数据展示

数据已经获取到了,下面就开始展示数据。我们准备采用UICollectionView来展示图片

新建ReadBookViewController控制器

class ReadBookViewController: BaseViewController {
    /// 绘本模型
    private let bookModel: BookModel
    
    init(bookModel: BookModel) {
        self.bookModel = bookModel
        /// 横屏展示
        if let delegate = UIApplication.shared.delegate as? AppDelegate {
            delegate.orientationMask = .landscapeRight
        }
        super.init(nibName: nil, bundle: nil)
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        /// 禁止侧滑返回
        navigationController?.interactivePopGestureRecognizer?.isEnabled = false
    }
    
    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        /// 取消禁止侧滑返回
        navigationController?.interactivePopGestureRecognizer?.isEnabled = true
        /// 取消横屏展示
        if let delegate = UIApplication.shared.delegate as? AppDelegate {
            delegate.orientationMask = .portrait
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        setupNav()
        addSubviews()
    }

    private func setupNav() {
        /// 隐藏导航栏
        navigation.bar.isHidden = true
    }
    
    private func addSubviews() {
    
    }
}
复制代码

创建collectionView

private lazy var collectionView: UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    layout.itemSize = UIScreen.main.bounds.size
    layout.scrollDirection = .horizontal
    layout.minimumLineSpacing = 0
    layout.minimumInteritemSpacing = 0
    let view = UICollectionView(frame: .zero, collectionViewLayout: layout)
    view.backgroundColor = .black
    view.delegate = self
    view.dataSource = self
    view.register(ReadBookCell.self)
    view.showsVerticalScrollIndicator = false
    view.showsHorizontalScrollIndicator = false
    view.isPagingEnabled = true
    return view
}()

private func addSubviews() {
    view.addSubview(collectionView)

    collectionView.snp.makeConstraints { (make) in
        make.edges.equalToSuperview()
    }
}

extension ReadBookViewController: UICollectionViewDelegate, UICollectionViewDataSource {

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return bookModel.pagesv2.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withClass: ReadBookCell.self, for: indexPath)
        cell.imgView.image = UIImage(contentsOfFile: bookModel.pagesv2[indexPath.item].imageURL)
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    }
}
复制代码

现在图片已经展示出来了

readbookgif.gif

播放音频

音频播放就用上次我们封装的

创建player

private lazy var player: AudioPlayer = {
    let player = AudioPlayer()
    player.delegate = self
    player.playbackPausesWhenResigningActive = false
    player.playbackPausesWhenBackgrounded = false
    player.playbackResumesWhenBecameActive = false
    player.playbackResumesWhenEnteringForeground = false
    return player
}()

extension ReadBookViewController: AudioPlayerDelegate {

    func playerStateDidChange(_ player: AudioPlayer) {}

    func playerCurrentTimeDidChange(_ player: AudioPlayer) {}

    func playerPlaybackDidEnd(_ player: AudioPlayer) {}

    func player(_ player: AudioPlayer, didFailWithError error: Error?) {}
}
复制代码

播放

private func playerURL() {
    /// 边界处理
    if playerIndex < 0 || playerIndex > bookModel.pagesv2.count - 1 {
        return
    }
    let model = bookModel.pagesv2[playerIndex]
    player.player(URL(fileURLWithPath: model.audioURL).absoluteString)
}
复制代码

图片和音频联动

  • 调用UIScrollViewDelegate的方法
extension ReadBookViewController: UIScrollViewDelegate {
    /// 滑动结束调用该方法
    func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
        debugPrint(scrollView.contentOffset.x)
        let offsetX = collectionView.contentOffset.x
        let currentIndex = Int(offsetX / UIScreen.width)
        if (currentIndex != playerIndex) {
            playerIndex = currentIndex
            playerURL()
        }
    }
    
    func scrollViewDidEndScrollingAnimation(_ scrollView: UIScrollView) {
        debugPrint(scrollView.contentOffset.x)
        let offsetX = collectionView.contentOffset.x
        let currentIndex = Int(offsetX / UIScreen.width)
        if (currentIndex != playerIndex) {
            playerIndex = currentIndex
            playerURL()
        }
    }
}
复制代码
  • 音频播放结束之后,设置collectionViewsetContentOffset方法翻页
extension ReadBookViewController: AudioPlayerDelegate {

    func playerPlaybackDidEnd(_ player: AudioPlayer) {
        if playerIndex < 0 || playerIndex + 1 >= bookModel.pagesv2.count - 1 {
            return
        }
        let offsetX = UIScreen.width * CGFloat(playerIndex + 1)
        collectionView.setContentOffset(CGPoint(x: offsetX, y: 0), animated: true)
    }
}
复制代码

到这读绘本就结束了

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