// // SPCoinRechargeView.swift // MoviaBox // // Created by 佳尔 on 2025/4/28. // import UIKit class SPCoinRechargeView: UIView { override var intrinsicContentSize: CGSize { return CGSize(width: kSPScreenWidth, height: 34 + self.collectionView.contentSize.height + 1) } private var currentModel: SPPayTemplateItem? ///充值成功回调 var rechargeFinishHandle: (() -> Void)? var dataArr: [SPPayTemplateItem]? { didSet { listDataArr.removeAll() var bigArr: [SPPayTemplateItem] = [] var smallArr: [SPPayTemplateItem] = [] dataArr?.forEach({ if $0.size == .big { bigArr.append($0) } else { smallArr.append($0) } }) if bigArr.count > 0 { listDataArr.append(bigArr) } if smallArr.count > 0 { listDataArr.append(smallArr) } UIView.performWithoutAnimation { [weak self] in self?.collectionView.reloadData() } self.collectionView.performBatchUpdates(nil) { [weak self] _ in self?.invalidateIntrinsicContentSize() } } } private lazy var listDataArr: [[SPPayTemplateItem]] = [] var userInfo: SPUserInfo? { didSet { coinLabel.text = "\((userInfo?.coin_left_total ?? 0) + (userInfo?.send_coin_left_total ?? 0))" } } var shortPlayId: String? var videoId: String? //MARK: UI属性 private lazy var coinNameLabel: UILabel = { let label = UILabel() label.font = .fontRegular(ofSize: 14) label.textColor = .colorFFFFFF(alpha: 0.7) label.text = "movia_coins_balance".localized + ":" return label }() private lazy var coinIconImageView: UIImageView = { let imageView = UIImageView(image: UIImage(named: "coin_icon_04")) return imageView }() private lazy var coinLabel: UILabel = { let label = UILabel() label.font = .fontRegular(ofSize: 14) label.textColor = .colorFFFFFF() return label }() private lazy var collectionViewLayout: WaterfallMutiSectionFlowLayout = { let layout = WaterfallMutiSectionFlowLayout() layout.delegate = self return layout }() private lazy var collectionView: SPCollectionView = { let collectionView = SPCollectionView(frame: .zero, collectionViewLayout: collectionViewLayout) collectionView.delegate = self collectionView.dataSource = self collectionView.showsVerticalScrollIndicator = false collectionView.showsHorizontalScrollIndicator = false collectionView.layer.masksToBounds = false SPCoinRechargeBigCell.registerCell(collectionView: collectionView, SPPayTemplateItem.SizeType.big.rawValue) SPCoinRechargeSmallCell.registerCell(collectionView: collectionView, SPPayTemplateItem.SizeType.small.rawValue) return collectionView }() override init(frame: CGRect) { super.init(frame: frame) _setupUI() } required init?(coder: NSCoder) { fatalError("init(coder:) has not been implemented") } } extension SPCoinRechargeView { private func _setupUI() { addSubview(coinNameLabel) addSubview(coinIconImageView) addSubview(coinLabel) addSubview(collectionView) coinNameLabel.snp.makeConstraints { make in make.left.equalToSuperview().offset(16) make.top.equalToSuperview() make.height.equalTo(20) } coinIconImageView.snp.makeConstraints { make in make.centerY.equalTo(coinNameLabel) make.left.equalTo(coinNameLabel.snp.right).offset(4) } coinLabel.snp.makeConstraints { make in make.centerY.equalTo(coinNameLabel) make.left.equalTo(coinIconImageView.snp.right).offset(4) } collectionView.snp.makeConstraints { make in make.left.right.bottom.equalToSuperview() make.top.equalToSuperview().offset(34) } } } //MARK: -------------- UICollectionViewDelegate & UICollectionViewDataSource -------------- extension SPCoinRechargeView: UICollectionViewDelegate, UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let model = self.listDataArr[indexPath.section][indexPath.row] let size = model.size ?? .small let cell = SPCoinRechargeCell.dequeueReusableCell(collectionView: collectionView, indexPath: indexPath, size.rawValue) cell.sp_isSelected = model == currentModel cell.model = model return cell } func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return self.listDataArr[section].count } func numberOfSections(in collectionView: UICollectionView) -> Int { return self.listDataArr.count } func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { let model = self.listDataArr[indexPath.section][indexPath.row] currentModel = model collectionView.reloadData() SPIAPManager.manager.startRecharge(model: model, shortPlayId: shortPlayId, videoId: videoId) { [weak self] finish in if finish { self?.rechargeFinishHandle?() } } } } //MARK: -------------- WaterfallMutiSectionDelegate -------------- extension SPCoinRechargeView: WaterfallMutiSectionDelegate { func columnNumber(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> Int { let model = self.listDataArr[section].last if model?.size == .big { return 2 } else { return 3 } } func heightForRowAtIndexPath(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, indexPath: IndexPath, itemWidth: CGFloat) -> CGFloat { let model = self.listDataArr[indexPath.section][indexPath.row] if model.size == .big { return 114 } else { return 126 } } func insetForSection(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> UIEdgeInsets { return .init(top: 0, left: 15, bottom: 0, right: 15) } func lineSpacing(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGFloat { return 15 } func interitemSpacing(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGFloat { return 15 } func referenceSizeForHeader(collectionView collection: UICollectionView, layout: WaterfallMutiSectionFlowLayout, section: Int) -> CGSize { if section == 0 { return .init(width: kSPScreenWidth, height: 0) } else { return .init(width: kSPScreenWidth, height: 15) } } }