这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战
前言
上一篇我们把下载并解压就已经做好了,现在我们就开始对解压后的文件进行处理
读绘本其实就是一张图片配个音频,滑到哪张图片播放哪个音频,绘本信息都是在index.json
文件里面,现在我们就来解析index.json
文件
获取数据
- 根据
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) {
}
}
复制代码
现在图片已经展示出来了
播放音频
音频播放就用上次我们封装的
创建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()
}
}
}
复制代码
- 音频播放结束之后,设置
collectionView
的setContentOffset
方法翻页
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