diff --git a/MoviaBox/Base/Extension/UIColor+SPAdd.swift b/MoviaBox/Base/Extension/UIColor+SPAdd.swift index 87686c8..6db3dfb 100644 --- a/MoviaBox/Base/Extension/UIColor+SPAdd.swift +++ b/MoviaBox/Base/Extension/UIColor+SPAdd.swift @@ -480,5 +480,13 @@ extension UIColor { static func colorAD7433(alpha: CGFloat = 1) -> UIColor { return color(hex: 0xAD7433, alpha: alpha) } + + static func colorFFC234(alpha: CGFloat = 1) -> UIColor { + return color(hex: 0xFFC234, alpha: alpha) + } + + static func colorFFDD00(alpha: CGFloat = 1) -> UIColor { + return color(hex: 0xFFDD00, alpha: alpha) + } } diff --git a/MoviaBox/Base/Networking/API/SPHomeAPI.swift b/MoviaBox/Base/Networking/API/SPHomeAPI.swift index 46f0dfd..690ead8 100644 --- a/MoviaBox/Base/Networking/API/SPHomeAPI.swift +++ b/MoviaBox/Base/Networking/API/SPHomeAPI.swift @@ -38,7 +38,7 @@ class SPHomeAPI: NSObject { ///首页模块接口 static func requestHomeModuleData(completer: ((_ model: SPHomeModuleModel?) -> Void)?) { var param = SPNetworkParameters(path: "/homeModuleData") -// let param = SPNetworkParameters(path: "/homeBannerAndNineSquare") +// var param = SPNetworkParameters(path: "/home/all-modules") param.method = .get SPNetwork.request(parameters: param) { (response: SPNetworkResponse) in diff --git a/MoviaBox/Base/Networking/API/SPVideoAPI.swift b/MoviaBox/Base/Networking/API/SPVideoAPI.swift index 03bcc49..cb44a1a 100644 --- a/MoviaBox/Base/Networking/API/SPVideoAPI.swift +++ b/MoviaBox/Base/Networking/API/SPVideoAPI.swift @@ -151,7 +151,7 @@ class SPVideoAPI: NSObject { } } - ///获取分类短剧 + ///获取分类短剧 static func requestCategoryShortList(page: Int, id: String, completer: ((_ listModel: SPListModel?) -> Void)?) { var param = SPNetworkParameters(path: "/videoList") param.method = .get diff --git a/MoviaBox/Class/Home/Controller/SPHomeViewController.swift b/MoviaBox/Class/Home/Controller/SPHomeViewController.swift index fa33070..2536e41 100644 --- a/MoviaBox/Class/Home/Controller/SPHomeViewController.swift +++ b/MoviaBox/Class/Home/Controller/SPHomeViewController.swift @@ -78,6 +78,8 @@ class SPHomeViewController: SPHomeChildController { return collectionView }() + private var headerView: SPHomeHeaderView? + override func viewDidLoad() { super.viewDidLoad() @@ -105,6 +107,13 @@ class SPHomeViewController: SPHomeChildController { requestPlayHistory() } super.viewDidAppear(animated) + + self.headerView?.isDidAppear = self.isDidAppear + } + + override func viewDidDisappear(_ animated: Bool) { + super.viewDidDisappear(animated) + self.headerView?.isDidAppear = self.isDidAppear } override func handleHeaderRefresh(_ completer: (() -> Void)?) { @@ -228,6 +237,7 @@ extension SPHomeViewController: UICollectionViewDelegate, UICollectionViewDataSo func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { if let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "headerView", for: indexPath) as? SPHomeHeaderView { headerView.viewModel = self.viewModel + self.headerView = headerView return headerView } return UICollectionReusableView() @@ -259,12 +269,22 @@ extension SPHomeViewController { requestListDataArr(page: 1) { [weak self] in self?.requestGroup.leave() } + self.requestGroup.enter() + requestCategoryShortList(id: "3") { [weak self] in + self?.requestGroup.leave() + } +// self.requestGroup.enter() +// requestCategoryShortList(id: "1") { [weak self] in +// self?.requestGroup.leave() +// } + self.requestGroup.notify(queue: DispatchQueue.main) { completer?() } } + ///获取模版数据 包括banner 九宫格等 private func requestModuleData(completer: (() -> Void)? = nil) { SPHomeAPI.requestHomeModuleData { [weak self] model in guard let self = self else { return } @@ -279,6 +299,28 @@ extension SPHomeViewController { } } + + ///甜宠ID= 3 + ///虐恋ID=1 + private func requestCategoryShortList(id: String, completer: (() -> Void)?) { + + SPVideoAPI.requestCategoryShortList(page: 1, id: id) { [weak self] listModel in + guard let self = self else { return } + + if let list = listModel?.list { + if id == "3" { + self.viewModel.categoryDataArr1 = list + } else { + self.viewModel.categoryDataArr2 = list + } + self.layout.headerReferenceSize = CGSize(width: kSPScreenWidth, height: SPHomeHeaderView.contentHeight(viewModel: self.viewModel)) + self.collectionView.reloadData() + } + self.updateEmptyState() + completer?() + } + } + ///获取播放记录 private func requestPlayHistory(completer: (() -> Void)? = nil) { SPVideoAPI.requestPlayHistoryList(page: 1) { [weak self] listModel in diff --git a/MoviaBox/Class/Home/View/SPHomeCategoryVideoCell.swift b/MoviaBox/Class/Home/View/SPHomeCategoryVideoCell.swift new file mode 100644 index 0000000..6b1449a --- /dev/null +++ b/MoviaBox/Class/Home/View/SPHomeCategoryVideoCell.swift @@ -0,0 +1,40 @@ +// +// SPHomeCategoryVideoCell.swift +// MoviaBox +// +// Created by 佳尔 on 2025/5/15. +// + +import UIKit + +class SPHomeCategoryVideoCell: SPCollectionViewCell { + + var model: SPShortModel? { + didSet { + coverImageView.sp_setImage(url: model?.image_url) + } + } + + private lazy var coverImageView: SPImageView = { + let imageView = SPImageView() + imageView.layer.cornerRadius = 8 + imageView.layer.masksToBounds = true + return imageView + }() + + override init(frame: CGRect) { + super.init(frame: frame) + + contentView.addSubview(coverImageView) + + coverImageView.snp.makeConstraints { make in + make.edges.equalToSuperview() + } + + } + + @MainActor required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + +} diff --git a/MoviaBox/Class/Home/View/SPHomeCategoryVideoView.swift b/MoviaBox/Class/Home/View/SPHomeCategoryVideoView.swift new file mode 100644 index 0000000..0141b5a --- /dev/null +++ b/MoviaBox/Class/Home/View/SPHomeCategoryVideoView.swift @@ -0,0 +1,257 @@ +// +// SPHomeCategoryVideoView.swift +// MoviaBox +// +// Created by 佳尔 on 2025/5/15. +// + +import UIKit + +class SPHomeCategoryVideoView: UIView { + + static func contentHeight() -> CGFloat { + return 372 + } + + override var intrinsicContentSize: CGSize { + let width = kSPScreenWidth + return CGSize(width: width, height: Self.contentHeight()) + } + + + var image: UIImage? { + didSet { + bgImageView.image = image + } + } + + var dataArr: [SPShortModel] = [] { + didSet { + if dataArr.count > 10 { + topDataArr = Array(dataArr.prefix(10)) + bottomDataArr = Array(dataArr.suffix(from: dataArr.count - 10)) + } else { + topDataArr = dataArr + bottomDataArr.removeAll() + } + self.topCollectionView.reloadData() + + updateTimerState() + + } + } + + var isDidAppear: Bool = false { + didSet { + updateTimerState() + } + } + + private lazy var topDataArr: [SPShortModel] = [] + private lazy var bottomDataArr: [SPShortModel] = [] + + private var timer: Timer? + + private var displayLink: CADisplayLink? + + ///被拖拽的View + private var draggingView: UIScrollView? + + //MARK: UI属性 + private lazy var bgImageView: UIImageView = { + let imageView = UIImageView() + imageView.isUserInteractionEnabled = true + return imageView + }() + + private lazy var collectionViewLayout: UICollectionViewFlowLayout = { + let layout = UICollectionViewFlowLayout() + layout.itemSize = CGSize(width: 101, height: 135) + layout.footerReferenceSize = CGSize(width: 8, height: 135) + layout.scrollDirection = .horizontal + layout.minimumLineSpacing = 8 + return layout + }() + + private lazy var topCollectionView: SPCollectionView = { + let collectionView = SPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) + collectionView.delegate = self + collectionView.dataSource = self + collectionView.showsHorizontalScrollIndicator = false + SPHomeCategoryVideoCell.registerCell(collectionView: collectionView) + return collectionView + }() + + private lazy var bottomCollectionView: SPCollectionView = { + let collectionView = SPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) + collectionView.delegate = self + collectionView.dataSource = self + collectionView.showsHorizontalScrollIndicator = false + SPHomeCategoryVideoCell.registerCell(collectionView: collectionView) + return collectionView + }() + + deinit { + self.displayLink?.invalidate() + self.timer?.invalidate() + } + + override init(frame: CGRect) { + super.init(frame: frame) + + _setupUI() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func updateTimerState() { + + if dataArr.count > 0, isDidAppear { + startTimer() + } else { + stopTimer() + } + } + + +} + +extension SPHomeCategoryVideoView { + private func startTimer() { +// if timer == nil { +// self.timer = Timer.scheduledTimer(timeInterval: 1, target: YYWeakProxy(target: self), selector: #selector(handleTimer), userInfo: nil, repeats: true) +// RunLoop.main.add(self.timer!, forMode: .common) +// } + + if displayLink == nil { + displayLink = CADisplayLink(target: YYWeakProxy(target: self), selector: #selector(handleTimer)) + displayLink?.add(to: .main, forMode: .common) + } + } + + private func stopTimer() { + timer?.invalidate() + timer = nil + + displayLink?.invalidate() + displayLink = nil + } + + @objc private func handleTimer() { + // 向左滑动 Top + if draggingView != topCollectionView { + let topOffset = CGPoint(x: topCollectionView.contentOffset.x + 0.5, y: 0) + if topOffset.x < topCollectionView.contentSize.width - topCollectionView.bounds.width { + topCollectionView.contentOffset = topOffset + } else { + topCollectionView.contentOffset = .zero + } + } + + // 向右滑动 Bottom + if draggingView != bottomCollectionView { + let bottomOffset = CGPoint(x: bottomCollectionView.contentOffset.x - 0.5, y: 0) + if bottomOffset.x > 0 { + bottomCollectionView.contentOffset = bottomOffset + } else { + bottomCollectionView.contentOffset = CGPoint(x: bottomCollectionView.contentSize.width - bottomCollectionView.bounds.width, y: 0) + } + } + } +} + +extension SPHomeCategoryVideoView { + + private func _setupUI() { + addSubview(bgImageView) + bgImageView.addSubview(topCollectionView) + bgImageView.addSubview(bottomCollectionView) + + bgImageView.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.right.equalToSuperview().offset(-16) + make.top.bottom.equalToSuperview() + } + + topCollectionView.snp.makeConstraints { make in + make.left.right.equalToSuperview() + make.top.equalToSuperview().offset(70) + make.height.equalTo(self.collectionViewLayout.itemSize.height) + } + + bottomCollectionView.snp.makeConstraints { make in + make.left.right.height.equalTo(topCollectionView) + make.top.equalTo(topCollectionView.snp.bottom).offset(8) + } + + } + +} + +//MARK: -------------- UICollectionViewDelegate & UICollectionViewDataSource -------------- +extension SPHomeCategoryVideoView: UICollectionViewDelegate, UICollectionViewDataSource { + + func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { + let model: SPShortModel + if collectionView == topCollectionView { + model = topDataArr[indexPath.row] + } else { + model = bottomDataArr[indexPath.row] + } + + let cell = SPHomeCategoryVideoCell.dequeueReusableCell(collectionView: collectionView, indexPath: indexPath) + cell.model = model + return cell + } + + func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { + if collectionView == topCollectionView { + return topDataArr.count + } else { + return bottomDataArr.count + } + } + + func numberOfSections(in collectionView: UICollectionView) -> Int { + return 3 + } + + func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { + let model: SPShortModel + if collectionView == topCollectionView { + model = topDataArr[indexPath.row] + } else { + model = bottomDataArr[indexPath.row] + } + + let vc = SPPlayerDetailViewController() + vc.shortPlayId = model.short_play_id + self.viewController?.navigationController?.pushViewController(vc, animated: true) + } + + func scrollViewWillBeginDragging(_ scrollView: UIScrollView) { + draggingView = scrollView + } + + func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) { + draggingView = nil + } + + func scrollViewDidScroll(_ scrollView: UIScrollView) { + + let offsetX = scrollView.contentOffset.x + let contentWidth = scrollView.contentSize.width + let sectionWidth = contentWidth / 3 + + if contentWidth <= scrollView.size.width { return } + + if offsetX < sectionWidth { + scrollView.contentOffset = CGPoint(x: sectionWidth * 2, y: 0) + } else if offsetX > sectionWidth * 2 { + scrollView.contentOffset = CGPoint(x: sectionWidth, y: 0) + } + } + +} diff --git a/MoviaBox/Class/Home/View/SPHomeDataItemView.swift b/MoviaBox/Class/Home/View/SPHomeDataItemView.swift index 7ed5d89..c691bc0 100644 --- a/MoviaBox/Class/Home/View/SPHomeDataItemView.swift +++ b/MoviaBox/Class/Home/View/SPHomeDataItemView.swift @@ -30,7 +30,7 @@ class SPHomeDataItemView: UIView { private(set) lazy var titleLabel: UILabel = { let label = UILabel() - label.font = .fontWeight(ofSize: 18, weight: 400) + label.font = .fontMedium(ofSize: 18) label.textColor = .colorFFFFFF() return label }() diff --git a/MoviaBox/Class/Home/View/SPHomeHeaderView.swift b/MoviaBox/Class/Home/View/SPHomeHeaderView.swift index c140c61..48affa1 100644 --- a/MoviaBox/Class/Home/View/SPHomeHeaderView.swift +++ b/MoviaBox/Class/Home/View/SPHomeHeaderView.swift @@ -34,9 +34,23 @@ class SPHomeHeaderView: UICollectionReusableView { exploreView.titleLabel.text = moduleModel?.nineSquare?.title exploreView.dataArr = list } - -// stackView.addArrangedSubview(trendingView) -// trendingView.dataArr = moduleModel?.bannerData + + if let list = viewModel?.categoryDataArr1, list.count > 0 { + stackView.addArrangedSubview(categoryVideoView1) + categoryVideoView1.dataArr = list + } + + if let list = moduleModel?.hotData, list.count > 0 { + stackView.addArrangedSubview(trendingView) + trendingView.dataArr = list + } + + if let list = viewModel?.categoryDataArr2, list.count > 0 { + stackView.addArrangedSubview(categoryVideoView2) + categoryVideoView2.dataArr = list + } + + // // stackView.addArrangedSubview(hotView) // hotView.dataArr = moduleModel?.bannerData @@ -50,6 +64,13 @@ class SPHomeHeaderView: UICollectionReusableView { } } + var isDidAppear: Bool = false { + didSet { + self.categoryVideoView1.isDidAppear = isDidAppear + self.categoryVideoView2.isDidAppear = isDidAppear + } + } + private lazy var stackView: UIStackView = { let view = UIStackView() @@ -93,6 +114,20 @@ class SPHomeHeaderView: UICollectionReusableView { return view }() + ///甜宠 + private lazy var categoryVideoView1: SPHomeCategoryVideoView = { + let view = SPHomeCategoryVideoView() + view.image = UIImage(named: "category_bg_image_01") + return view + }() + + ///虐恋 + private lazy var categoryVideoView2: SPHomeCategoryVideoView = { + let view = SPHomeCategoryVideoView() + view.image = UIImage(named: "category_bg_image_02") + return view + }() + private lazy var trendingView: SPHomeTrendingView = { let view = SPHomeTrendingView() return view @@ -111,6 +146,7 @@ class SPHomeHeaderView: UICollectionReusableView { private lazy var titleView: SPHomeDataItemView = { let view = SPHomeDataItemView() view.titleLabel.text = "movia_more_for_you".localized + view.iconImageView.image = UIImage(named: "mark_icon_02") return view }() @@ -228,7 +264,29 @@ extension SPHomeHeaderView { height = height + SPHomeExploreView.contentHeight(dataArr: list) } -// height = height + SPHomeTrendingView.contentHeight(dataArr: moduleModel?.bannerData ?? []) + 25 + ///甜宠数据 + if viewModel.categoryDataArr1.count > 0 { + if height > 0 { + height = height + 25 + } + height = height + SPHomeCategoryVideoView.contentHeight() + } + + ///虐恋 + if viewModel.categoryDataArr2.count > 0 { + if height > 0 { + height = height + 25 + } + height = height + SPHomeCategoryVideoView.contentHeight() + } + + if let list = moduleModel?.hotData, list.count > 0 { + if height > 0 { + height = height + 25 + } + height = height + SPHomeTrendingView.contentHeight(dataArr: list) + } + // // // height = height + SPHomeHotView.contentHeight(dataArr: moduleModel?.bannerData ?? []) + 25 diff --git a/MoviaBox/Class/Home/View/SPHomeTrendingCell.swift b/MoviaBox/Class/Home/View/SPHomeTrendingCell.swift index 0f457ef..65a52bb 100644 --- a/MoviaBox/Class/Home/View/SPHomeTrendingCell.swift +++ b/MoviaBox/Class/Home/View/SPHomeTrendingCell.swift @@ -13,37 +13,82 @@ class SPHomeTrendingCell: SPCollectionViewCell { didSet { coverImageView.sp_setImage(url: model?.image_url) titleLabel.text = model?.name + hotView.setTitle("\(model?.watch_total ?? 0)", for: .normal) + + if let tag = model?.tag_type, !tag.isEmpty { + tagView.setTitle(tag, for: .normal) + tagView.isHidden = false + } else { + tagView.isHidden = true + } } } + var row: Int = 0 { + didSet { + let num = row + 1 + if num < 4 { + numBgView.image = UIImage(named: "num_bg_icon_\(num)") + } else { + numBgView.image = UIImage(named: "num_bg_icon_4") + } + + numLabel.text = "\(num)" + } + } + + //MARK: UI属性 private lazy var coverImageView: SPImageView = { let imageView = SPImageView() - imageView.layer.cornerRadius = 10 + imageView.layer.cornerRadius = 6 imageView.layer.masksToBounds = true return imageView }() + private lazy var numBgView: UIImageView = { + let imageView = UIImageView() + return imageView + }() + + private lazy var numLabel: UILabel = { + let label = UILabel() + label.font = .fontMedium(ofSize: 20) + label.textColor = .colorFFFFFF() + return label + }() + private lazy var titleLabel: UILabel = { let label = UILabel() - label.font = .fontLight(ofSize: 13) - label.textColor = .colorFFFFFF(alpha: 0.9) + label.font = .fontMedium(ofSize: 12) + label.textColor = .colorFFFFFF() label.numberOfLines = 2 return label }() - private lazy var hotBgView: SPGradientView = { - let view = SPGradientView() - view.colors = [UIColor.colorF56490().cgColor, UIColor.colorBF6BFF().cgColor] - view.startPoint = .init(x: 0.5, y: 0) - view.endPoint = .init(x: 0.5, y: 1) - view.locations = [0, 1] - view.addRadius(topLeft: 0, topRight: 0, bottomLeft: 0, bottomRight: 6) - return view + private lazy var hotView: JXButton = { + let button = JXButton(type: .custom) + button.isUserInteractionEnabled = false + button.titleDirection = .right + button.jx_font = .fontRegular(ofSize: 10) + button.leftAndRightMargin = 6 + button.setImage(UIImage(named: "hot_icon_01"), for: .normal) + button.setTitleColor(.colorFFDD00(), for: .normal) + button.backgroundColor = .colorD9D9D9(alpha: 0.16) + button.layer.cornerRadius = 2 + button.layer.masksToBounds = true + return button }() - private lazy var hotIconImageView: UIImageView = { - let imageView = UIImageView(image: UIImage(named: "hot_icon_01")) - return imageView + private lazy var tagView: JXButton = { + let button = JXButton(type: .custom) + button.isUserInteractionEnabled = false + button.backgroundColor = .colorD9D9D9(alpha: 0.16) + button.layer.cornerRadius = 2 + button.layer.masksToBounds = true + button.jx_font = .fontRegular(ofSize: 10) + button.setTitleColor(.colorFFFFFF(), for: .normal) + button.leftAndRightMargin = 6 + return button }() override init(frame: CGRect) { @@ -62,30 +107,45 @@ extension SPHomeTrendingCell { private func _setupUI() { contentView.addSubview(coverImageView) + coverImageView.addSubview(numBgView) + numBgView.addSubview(numLabel) contentView.addSubview(titleLabel) - coverImageView.addSubview(hotBgView) - hotBgView.addSubview(hotIconImageView) + contentView.addSubview(hotView) + contentView.addSubview(tagView) +// coverImageView.addSubview(hotBgView) +// hotBgView.addSubview(hotIconImageView) coverImageView.snp.makeConstraints { make in - make.left.right.top.equalToSuperview() - make.bottom.equalToSuperview().offset(-38) + make.left.top.bottom.equalToSuperview() + make.width.equalTo(82) + } + + numBgView.snp.makeConstraints { make in + make.left.top.equalToSuperview() + } + + numLabel.snp.makeConstraints { make in + make.center.equalToSuperview() } titleLabel.snp.makeConstraints { make in - make.left.equalToSuperview() - make.right.lessThanOrEqualToSuperview() - make.top.equalTo(coverImageView.snp.bottom).offset(5) + make.left.equalTo(coverImageView.snp.right).offset(8) + make.top.equalToSuperview().offset(12) + make.right.lessThanOrEqualToSuperview().offset(-5) } - hotBgView.snp.makeConstraints { make in - make.left.top.equalToSuperview() - make.width.equalTo(22) - make.height.equalTo(16) + hotView.snp.makeConstraints { make in + make.left.equalTo(titleLabel) + make.top.equalToSuperview().offset(56) + make.height.equalTo(18) } - hotIconImageView.snp.makeConstraints { make in - make.center.equalToSuperview() + tagView.snp.makeConstraints { make in + make.left.equalTo(hotView) + make.top.equalTo(hotView.snp.bottom).offset(8) + make.height.equalTo(18) } + } } diff --git a/MoviaBox/Class/Home/View/SPHomeTrendingView.swift b/MoviaBox/Class/Home/View/SPHomeTrendingView.swift index edbf3f7..1eeaff9 100644 --- a/MoviaBox/Class/Home/View/SPHomeTrendingView.swift +++ b/MoviaBox/Class/Home/View/SPHomeTrendingView.swift @@ -7,47 +7,44 @@ import UIKit -class SPHomeTrendingView: SPHomeDataItemView { +class SPHomeTrendingView: UIView { private static func itemSize() -> CGSize { - let width = floor((kSPScreenWidth - 15 * 2 - 12 * 2) / 3) - let imageScale: CGFloat = 153 / 107 - let height = width * imageScale + 38 - return CGSize(width: width, height: height) + return CGSize(width: 224, height: 106) } - override class func contentHeight(dataArr: [SPShortModel]) -> CGFloat { - - var height = self.contentToTop - - var lineCount = dataArr.count / 3 - if dataArr.count % 3 > 0 { - lineCount += 1 - } - - let contentHeight = itemSize().height * CGFloat(lineCount) + 12 * CGFloat(lineCount - 1) - if contentHeight > 0 { - height += contentHeight - } else { - height += 1 - } - - return height + class func contentHeight(dataArr: [SPShortModel]) -> CGFloat { + return 388 } - override var dataArr: [SPShortModel]? { + var dataArr: [SPShortModel]? { didSet { self.collectionView.reloadData() } } + + //MARK: UI属性 + private lazy var bgView: UIImageView = { + let view = UIImageView(image: UIImage(named: "category_bg_image_03")) + return view + }() + + private lazy var titleLabel: UILabel = { + let label = UILabel() + label.font = .fontMedium(ofSize: 18) + label.textColor = .colorFFC234() + return label + }() + private lazy var collectionViewLayout: UICollectionViewFlowLayout = { let layout = UICollectionViewFlowLayout() layout.minimumLineSpacing = 12 layout.minimumInteritemSpacing = 12 layout.itemSize = Self.itemSize() - layout.sectionInset = UIEdgeInsets(top: 0, left: 15, bottom: 0, right: 15) + layout.sectionInset = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16) + layout.scrollDirection = .horizontal return layout }() @@ -55,7 +52,9 @@ class SPHomeTrendingView: SPHomeDataItemView { let collectionView = SPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) collectionView.delegate = self collectionView.dataSource = self - collectionView.isScrollEnabled = false +// collectionView.isScrollEnabled = false + collectionView.showsVerticalScrollIndicator = false + collectionView.showsHorizontalScrollIndicator = false SPHomeTrendingCell.registerCell(collectionView: collectionView) return collectionView }() @@ -63,7 +62,6 @@ class SPHomeTrendingView: SPHomeDataItemView { override init(frame: CGRect) { super.init(frame: frame) - self.titleLabel.text = "movia_trending_now".localized _setupUI() @@ -77,10 +75,23 @@ class SPHomeTrendingView: SPHomeDataItemView { extension SPHomeTrendingView { private func _setupUI() { - contentView.addSubview(collectionView) + addSubview(bgView) + addSubview(titleLabel) + addSubview(collectionView) + + titleLabel.snp.makeConstraints { make in + make.left.equalToSuperview().offset(16) + make.top.equalToSuperview().offset(14) + } + + bgView.snp.makeConstraints { make in + make.left.equalToSuperview() + make.top.equalToSuperview() + } collectionView.snp.makeConstraints { make in - make.edges.equalToSuperview() + make.left.right.bottom.equalToSuperview() + make.top.equalToSuperview().offset(46) } } @@ -90,6 +101,7 @@ extension SPHomeTrendingView { extension SPHomeTrendingView: UICollectionViewDataSource, UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = SPHomeTrendingCell.dequeueReusableCell(collectionView: collectionView, indexPath: indexPath) + cell.row = indexPath.row cell.model = dataArr?[indexPath.row] return cell } diff --git a/MoviaBox/Class/Home/ViewModel/SPHomeViewModel.swift b/MoviaBox/Class/Home/ViewModel/SPHomeViewModel.swift index fbcc5ea..cc22b20 100644 --- a/MoviaBox/Class/Home/ViewModel/SPHomeViewModel.swift +++ b/MoviaBox/Class/Home/ViewModel/SPHomeViewModel.swift @@ -12,8 +12,15 @@ class SPHomeViewModel: NSObject { lazy var page = 1 lazy var dataArr: [SPShortModel] = [] + ///模版数据 var moduleModel: SPHomeModuleModel? + ///分类数据 + ///甜宠 + var categoryDataArr1: [SPShortModel] = [] + ///虐恋 + var categoryDataArr2: [SPShortModel] = [] + ///历史记录 var playHistoryArr: [SPShortModel]? diff --git a/MoviaBox/Class/Player/Controller/SPPlayerListViewController.swift b/MoviaBox/Class/Player/Controller/SPPlayerListViewController.swift index fb23382..cd257bb 100644 --- a/MoviaBox/Class/Player/Controller/SPPlayerListViewController.swift +++ b/MoviaBox/Class/Player/Controller/SPPlayerListViewController.swift @@ -6,6 +6,7 @@ // import UIKit +import AVKit @objc protocol SPPlayerListViewControllerDelegate { @@ -274,21 +275,10 @@ extension SPPlayerListViewController { extension SPPlayerListViewController { ///点击播放或暂停 private func clickPauseOrPlay() { -// let model = self.dataArr[currentIndexPath.section] - ///打开支付页面 -// if self.onVideoPay() { -// return -// } - if self.viewModel.isPlaying { self.pause() -// self.viewModel.isPlaying = false -// self.viewModel.currentPlayer?.pause() } else { self.play() - -// self.viewModel.isPlaying = true -// self.viewModel.currentPlayer?.start() } } diff --git a/MoviaBox/Class/Player/Model/SPShortModel.swift b/MoviaBox/Class/Player/Model/SPShortModel.swift index b694a52..c147813 100644 --- a/MoviaBox/Class/Player/Model/SPShortModel.swift +++ b/MoviaBox/Class/Player/Model/SPShortModel.swift @@ -27,6 +27,7 @@ class SPShortModel: SPModel, SmartCodable { var short_play_video_id: String? var tag_type: String? var video_info: SPVideoInfoModel? + ///观看数 var watch_total: Int? var current_episode: String? var video_url: String? diff --git a/MoviaBox/Libs/Player/SPPlayer.swift b/MoviaBox/Libs/Player/SPPlayer.swift index f8e420e..3d1633a 100644 --- a/MoviaBox/Libs/Player/SPPlayer.swift +++ b/MoviaBox/Libs/Player/SPPlayer.swift @@ -66,6 +66,9 @@ class SPPlayer: NSObject { */ private var isAddIdleTimerDisabledObserver = false + ///音频占用情况 + private var interruptionType: AVAudioSession.InterruptionType? + ///总进度 var duration: Int { return Int(self.player.totalTime) @@ -103,11 +106,17 @@ class SPPlayer: NSObject { var isLoop = true deinit { + NotificationCenter.default.removeObserver(self) self.stop() } override init() { super.init() + //声音被打断的通知(电话打来) + NotificationCenter.default.addObserver(self, selector: #selector(interruptionNotification(sender:)), name: AVAudioSession.interruptionNotification, object: nil) + //耳机插入和拔出的通知 + NotificationCenter.default.addObserver(self, selector: #selector(routeChangeNotification(sender:)), name: AVAudioSession.routeChangeNotification, object: nil) + player.scalingMode = .aspectFill sp_addAction() } @@ -160,7 +169,9 @@ class SPPlayer: NSObject { func start() { self.isPlaying = true - player.play() + if self.interruptionType != .began { + player.play() + } UIApplication.shared.isIdleTimerDisabled = true self.addIdleTimerDisabledObserver() @@ -211,9 +222,9 @@ extension SPPlayer { //播放状态 player.playerPlayStateChanged = { [weak self] (asset, playState) in guard let self = self else { return } - if playState == .playStatePlaying, !isPlaying { + if playState == .playStatePlaying && !isPlaying { self.pause() - } else if playState == .playStatePaused, isPlaying { + } else if playState == .playStatePaused, isPlaying, self.interruptionType != .began { self.start() } switch playState { @@ -238,9 +249,9 @@ extension SPPlayer { //加载状态 player.playerLoadStateChanged = { [weak self] (asset, loadState) in guard let self = self else { return } - if loadState == .playable, !isPlaying { + if loadState == .playable && !isPlaying { self.pause() - } else if loadState == .playable, isPlaying, self.player.playState != .playStatePlaying { + } else if loadState == .playable, isPlaying, self.player.playState != .playStatePlaying, self.interruptionType != .began { self.start() } @@ -294,3 +305,26 @@ extension SPPlayer { } } + +//MARK: -------------- 监听视频中断 -------------- +extension SPPlayer { + + @objc private func interruptionNotification(sender: Notification) { + guard let userInfo = sender.userInfo else { return } + guard let interruptionType = userInfo[AVAudioSessionInterruptionTypeKey] as? UInt else { return } + + self.interruptionType = AVAudioSession.InterruptionType(rawValue: interruptionType) + if self.interruptionType == .began { + self.player.pause() + } else { + if self.isPlaying { + self.player.play() + } + } + + } + + @objc private func routeChangeNotification(sender: Notification) { +// self.pause() + } +} diff --git a/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/Contents.json b/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/Contents.json index 5472a49..60f4f9c 100644 --- a/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/Contents.json +++ b/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/Contents.json @@ -5,12 +5,12 @@ "scale" : "1x" }, { - "filename" : "hot@2x.png", + "filename" : "🔥@2x.png", "idiom" : "universal", "scale" : "2x" }, { - "filename" : "hot@3x.png", + "filename" : "🔥@3x.png", "idiom" : "universal", "scale" : "3x" } diff --git a/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/hot@2x.png b/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/hot@2x.png deleted file mode 100644 index 49c454f..0000000 Binary files a/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/hot@2x.png and /dev/null differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/hot@3x.png b/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/hot@3x.png deleted file mode 100644 index 7eb28b0..0000000 Binary files a/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/hot@3x.png and /dev/null differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/🔥@2x.png b/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/🔥@2x.png new file mode 100644 index 0000000..a262744 Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/🔥@2x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/🔥@3x.png b/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/🔥@3x.png new file mode 100644 index 0000000..2f6ca14 Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/icon/hot_icon_01.imageset/🔥@3x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/mark_icon_01.imageset/💗@2x.png b/MoviaBox/Source/Assets.xcassets/icon/mark_icon_01.imageset/💗@2x.png index afd6324..e85f913 100644 Binary files a/MoviaBox/Source/Assets.xcassets/icon/mark_icon_01.imageset/💗@2x.png and b/MoviaBox/Source/Assets.xcassets/icon/mark_icon_01.imageset/💗@2x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/mark_icon_01.imageset/💗@3x.png b/MoviaBox/Source/Assets.xcassets/icon/mark_icon_01.imageset/💗@3x.png index f09e083..eda4ed9 100644 Binary files a/MoviaBox/Source/Assets.xcassets/icon/mark_icon_01.imageset/💗@3x.png and b/MoviaBox/Source/Assets.xcassets/icon/mark_icon_01.imageset/💗@3x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/mark_icon_02.imageset/Contents.json b/MoviaBox/Source/Assets.xcassets/icon/mark_icon_02.imageset/Contents.json new file mode 100644 index 0000000..d9899d5 --- /dev/null +++ b/MoviaBox/Source/Assets.xcassets/icon/mark_icon_02.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Group 47@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Group 47@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MoviaBox/Source/Assets.xcassets/icon/mark_icon_02.imageset/Group 47@2x.png b/MoviaBox/Source/Assets.xcassets/icon/mark_icon_02.imageset/Group 47@2x.png new file mode 100644 index 0000000..60b7ab1 Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/icon/mark_icon_02.imageset/Group 47@2x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/mark_icon_02.imageset/Group 47@3x.png b/MoviaBox/Source/Assets.xcassets/icon/mark_icon_02.imageset/Group 47@3x.png new file mode 100644 index 0000000..4b54763 Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/icon/mark_icon_02.imageset/Group 47@3x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_1.imageset/Contents.json b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_1.imageset/Contents.json new file mode 100644 index 0000000..404e7db --- /dev/null +++ b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_1.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame 145@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame 145@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_1.imageset/Frame 145@2x.png b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_1.imageset/Frame 145@2x.png new file mode 100644 index 0000000..ddc227e Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_1.imageset/Frame 145@2x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_1.imageset/Frame 145@3x.png b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_1.imageset/Frame 145@3x.png new file mode 100644 index 0000000..5911336 Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_1.imageset/Frame 145@3x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_2.imageset/Contents.json b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_2.imageset/Contents.json new file mode 100644 index 0000000..403714c --- /dev/null +++ b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_2.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame 146@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame 146@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_2.imageset/Frame 146@2x.png b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_2.imageset/Frame 146@2x.png new file mode 100644 index 0000000..e7a9d39 Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_2.imageset/Frame 146@2x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_2.imageset/Frame 146@3x.png b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_2.imageset/Frame 146@3x.png new file mode 100644 index 0000000..661b1b8 Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_2.imageset/Frame 146@3x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_3.imageset/Contents.json b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_3.imageset/Contents.json new file mode 100644 index 0000000..ee04593 --- /dev/null +++ b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_3.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame 1912056663@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame 1912056663@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_3.imageset/Frame 1912056663@2x.png b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_3.imageset/Frame 1912056663@2x.png new file mode 100644 index 0000000..96ad557 Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_3.imageset/Frame 1912056663@2x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_3.imageset/Frame 1912056663@3x.png b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_3.imageset/Frame 1912056663@3x.png new file mode 100644 index 0000000..e3f4bfa Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_3.imageset/Frame 1912056663@3x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_4.imageset/Contents.json b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_4.imageset/Contents.json new file mode 100644 index 0000000..a8db168 --- /dev/null +++ b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_4.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame 58@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame 58@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_4.imageset/Frame 58@2x.png b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_4.imageset/Frame 58@2x.png new file mode 100644 index 0000000..e403bd2 Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_4.imageset/Frame 58@2x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_4.imageset/Frame 58@3x.png b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_4.imageset/Frame 58@3x.png new file mode 100644 index 0000000..9b2da1c Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/icon/num_bg_icon_4.imageset/Frame 58@3x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/image/category_bg_image_01.imageset/Contents.json b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_01.imageset/Contents.json new file mode 100644 index 0000000..85fd071 --- /dev/null +++ b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_01.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "甜宠类-卡片@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "甜宠类-卡片@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MoviaBox/Source/Assets.xcassets/image/category_bg_image_01.imageset/甜宠类-卡片@2x.png b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_01.imageset/甜宠类-卡片@2x.png new file mode 100644 index 0000000..e960b4d Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_01.imageset/甜宠类-卡片@2x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/image/category_bg_image_01.imageset/甜宠类-卡片@3x.png b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_01.imageset/甜宠类-卡片@3x.png new file mode 100644 index 0000000..4dbfb2b Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_01.imageset/甜宠类-卡片@3x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/image/category_bg_image_02.imageset/Contents.json b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_02.imageset/Contents.json new file mode 100644 index 0000000..40a2275 --- /dev/null +++ b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_02.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "虐恋类-卡片@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "虐恋类-卡片@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MoviaBox/Source/Assets.xcassets/image/category_bg_image_02.imageset/虐恋类-卡片@2x.png b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_02.imageset/虐恋类-卡片@2x.png new file mode 100644 index 0000000..f9da943 Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_02.imageset/虐恋类-卡片@2x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/image/category_bg_image_02.imageset/虐恋类-卡片@3x.png b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_02.imageset/虐恋类-卡片@3x.png new file mode 100644 index 0000000..94e52db Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_02.imageset/虐恋类-卡片@3x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/image/category_bg_image_03.imageset/Contents.json b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_03.imageset/Contents.json new file mode 100644 index 0000000..21d5df6 --- /dev/null +++ b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_03.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "scale" : "1x" + }, + { + "filename" : "Frame 131@2x.png", + "idiom" : "universal", + "scale" : "2x" + }, + { + "filename" : "Frame 131@3x.png", + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/MoviaBox/Source/Assets.xcassets/image/category_bg_image_03.imageset/Frame 131@2x.png b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_03.imageset/Frame 131@2x.png new file mode 100644 index 0000000..71d543e Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_03.imageset/Frame 131@2x.png differ diff --git a/MoviaBox/Source/Assets.xcassets/image/category_bg_image_03.imageset/Frame 131@3x.png b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_03.imageset/Frame 131@3x.png new file mode 100644 index 0000000..18101ef Binary files /dev/null and b/MoviaBox/Source/Assets.xcassets/image/category_bg_image_03.imageset/Frame 131@3x.png differ