// // 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) } } }