From 93a8ea36c1d8ba7f7811a9b32d3d7add007a57f0 Mon Sep 17 00:00:00 2001 From: zeng Date: Sun, 27 Apr 2025 10:37:08 +0800 Subject: [PATCH] =?UTF-8?q?banner=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Thimra/Base/Extension/UIColor+SPAdd.swift | 12 ++ .../View/SPZoomCollectionViewLayout.swift | 107 ------------------ Thimra/Class/Home/View/SPHomeHeaderView.swift | 44 ++++--- .../Home/View/SPHomeZoomBannerCell.swift | 2 +- .../Class/Mine/View/SPMineMemberNoView.swift | 31 ++++- Thimra/Source/en.lproj/Localizable.strings | 2 + .../ZKCycleScrollView.swift | 14 +++ .../ZKCycleScrollViewFlowLayout.swift | 43 ++++++- 8 files changed, 128 insertions(+), 127 deletions(-) delete mode 100644 Thimra/Base/View/SPZoomCollectionViewLayout.swift diff --git a/Thimra/Base/Extension/UIColor+SPAdd.swift b/Thimra/Base/Extension/UIColor+SPAdd.swift index 363acb1..58c4d5f 100644 --- a/Thimra/Base/Extension/UIColor+SPAdd.swift +++ b/Thimra/Base/Extension/UIColor+SPAdd.swift @@ -212,5 +212,17 @@ extension UIColor { static func colorFFD791(alpha: CGFloat = 1) -> UIColor { return color(hex: 0xFFD791, alpha: alpha) } + + static func color262014(alpha: CGFloat = 1) -> UIColor { + return color(hex: 0x262014, alpha: alpha) + } + + static func colorA69B89(alpha: CGFloat = 1) -> UIColor { + return color(hex: 0xA69B89, alpha: alpha) + } + + static func colorFFD28F(alpha: CGFloat = 1) -> UIColor { + return color(hex: 0xFFD28F, alpha: alpha) + } } diff --git a/Thimra/Base/View/SPZoomCollectionViewLayout.swift b/Thimra/Base/View/SPZoomCollectionViewLayout.swift deleted file mode 100644 index ab6b551..0000000 --- a/Thimra/Base/View/SPZoomCollectionViewLayout.swift +++ /dev/null @@ -1,107 +0,0 @@ -// -// SPZoomCollectionViewLayout.swift -// Thimra -// -// Created by Overseas on 2025/4/22. -// - -import UIKit - -class SPZoomCollectionViewLayout: UICollectionViewFlowLayout { - - let minimumScale: CGFloat = 0.08 // 调整缩放大小 - - private(set) var currentIndexPath: IndexPath = IndexPath(row: 0, section: 0) - - - private var cellWidth: CGFloat { - return itemSize.width + minimumLineSpacing - } - - override func prepare() { - super.prepare() - scrollDirection = .horizontal - self.collectionView?.decelerationRate = .fast - let screenWidth = UIScreen.main.bounds.size.width - let insetLeft = (screenWidth - self.itemSize.width) / 2 - collectionView?.contentInset = UIEdgeInsets(top: 0, left: insetLeft, bottom: 0, right: insetLeft) - } - - override func targetContentOffset(forProposedContentOffset proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint { - guard let collectionView = collectionView else { return super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity) } - - let proposedRect = CGRect(x: proposedContentOffset.x, y: 0, width: collectionView.bounds.width, height: collectionView.bounds.height) - - guard let layoutAttributes = layoutAttributesForElements(in: proposedRect) else { - return super.targetContentOffset(forProposedContentOffset: proposedContentOffset, withScrollingVelocity: velocity) - } - - let horizontalCenterX = proposedContentOffset.x + collectionView.bounds.width / 2 - var offsetAdjustment = CGFloat.greatestFiniteMagnitude -// ydLog(message: "offsetAdjustment = \(offsetAdjustment)") -// ydLog(message: "horizontalCenterX = \(horizontalCenterX)") - - var currentIndexPath: IndexPath = IndexPath(row: 0, section: 0) - for attributes in layoutAttributes { - let itemHorizontalCenterX = attributes.center.x - let distance = itemHorizontalCenterX - horizontalCenterX -// ydLog(message: "distance = \(distance)") - //离中心距离最近的 - if abs(distance) < abs(offsetAdjustment) { - offsetAdjustment = distance - currentIndexPath = attributes.indexPath - } - } - self.currentIndexPath = currentIndexPath - - let point = CGPoint(x: proposedContentOffset.x + offsetAdjustment, y: proposedContentOffset.y) -// ydLog(message: "proposedContentOffset = \(proposedContentOffset)") -// ydLog(message: "offsetAdjustment = \(offsetAdjustment)") -// ydLog(message: "point = \(point)") -// ydLog(message: "currentIndex = \(currentIndex)") - - return point - } - - override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { - guard let collectionView = collectionView else { return nil } - - let visibleRect = CGRect(origin: collectionView.contentOffset, size: collectionView.bounds.size) - let attributes = super.layoutAttributesForElements(in: rect)?.compactMap { $0.copy() as? UICollectionViewLayoutAttributes } - - for attribute in attributes ?? [] { - let distance = visibleRect.midX - attribute.center.x - let normalizedDistance = distance / (collectionView.bounds.width * 0.5) - let zoom = 1 - abs(normalizedDistance) * minimumScale - - //缩放 - let scaleTransform = CGAffineTransform(scaleX: zoom, y: zoom) - - - //旋转 - let rotationAngle = kSPAngleToRadians(angle: -normalizedDistance * 4) - let rotationTransform = CGAffineTransform(rotationAngle: rotationAngle) - - // 组合旋转和缩放变换 - let combinedTransform = rotationTransform.concatenating(scaleTransform) - // 应用变换 - attribute.transform = combinedTransform - - var alpha = 1.8 - abs(normalizedDistance) - if alpha < 0 { - alpha = 0 - } else if alpha > 1 { - alpha = 1 - } - attribute.alpha = alpha - } - - return attributes - } - - override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { - return true - } - - -} diff --git a/Thimra/Class/Home/View/SPHomeHeaderView.swift b/Thimra/Class/Home/View/SPHomeHeaderView.swift index 99092c7..ba45859 100644 --- a/Thimra/Class/Home/View/SPHomeHeaderView.swift +++ b/Thimra/Class/Home/View/SPHomeHeaderView.swift @@ -50,21 +50,17 @@ class SPHomeHeaderView: UICollectionReusableView { return view }() - private lazy var bannerLayout: SPZoomCollectionViewLayout = { - let layout = SPZoomCollectionViewLayout() - layout.itemSize = .init(width: 234, height: Self.bannerHeight()) - layout.minimumLineSpacing = 10 - layout.minimumInteritemSpacing = 0 - return layout - }() - - private lazy var bannerView: SPCollectionView = { - let view = SPCollectionView(frame: .zero, collectionViewLayout: bannerLayout) + private lazy var bannerView: ZKCycleScrollView = { + let view = ZKCycleScrollView(frame: .zero, shouldInfiniteLoop: true) + view.itemSize = .init(width: 234, height: Self.bannerHeight()) + view.itemAlpha = true + view.itemZoomScale = 0.9 + view.itemSpacing = 10 + view.rotationAngle = 5 view.delegate = self view.dataSource = self - view.showsVerticalScrollIndicator = false - view.showsHorizontalScrollIndicator = false - SPHomeZoomBannerCell.registerCell(collectionView: view) + view.hidesPageControl = true + view.register(SPHomeZoomBannerCell.self, forCellWithReuseIdentifier: "banner") view.snp.makeConstraints { make in make.width.equalTo(kSPScreenWidth) @@ -153,6 +149,28 @@ extension SPHomeHeaderView: UICollectionViewDelegate, UICollectionViewDataSource } } +//MARK: -------------- ZKCycleScrollViewDelegate & ZKCycleScrollViewDataSource -------------- +extension SPHomeHeaderView: ZKCycleScrollViewDelegate, ZKCycleScrollViewDataSource { + + func cycleScrollView(_ cycleScrollView: ZKCycleScrollView, cellForItemAt index: Int) -> ZKCycleScrollViewCell { + let cell = cycleScrollView.dequeueReusableCell(withReuseIdentifier: "banner", for: index) as! SPHomeZoomBannerCell + cell.model = self.viewModel?.moduleModel?.bannerData?[index] + return cell + } + + func numberOfItems(in cycleScrollView: ZKCycleScrollView) -> Int { + return self.viewModel?.moduleModel?.bannerData?.count ?? 0 + } + + func cycleScrollView(_ cycleScrollView: ZKCycleScrollView, didSelectItemAt index: Int) { + let model = self.viewModel?.moduleModel?.bannerData?[index] + + let vc = SPPlayerDetailViewController() + vc.shortPlayId = model?.short_play_id + self.viewController?.navigationController?.pushViewController(vc, animated: true) + } +} + extension SPHomeHeaderView { diff --git a/Thimra/Class/Home/View/SPHomeZoomBannerCell.swift b/Thimra/Class/Home/View/SPHomeZoomBannerCell.swift index d915c1f..12bc3a7 100644 --- a/Thimra/Class/Home/View/SPHomeZoomBannerCell.swift +++ b/Thimra/Class/Home/View/SPHomeZoomBannerCell.swift @@ -7,7 +7,7 @@ import UIKit -class SPHomeZoomBannerCell: SPCollectionViewCell { +class SPHomeZoomBannerCell: ZKCycleScrollViewCell { var model: SPShortModel? { didSet { diff --git a/Thimra/Class/Mine/View/SPMineMemberNoView.swift b/Thimra/Class/Mine/View/SPMineMemberNoView.swift index a15f10d..0dfd7a9 100644 --- a/Thimra/Class/Mine/View/SPMineMemberNoView.swift +++ b/Thimra/Class/Mine/View/SPMineMemberNoView.swift @@ -25,7 +25,6 @@ class SPMineMemberNoView: UIView { return label }() - private lazy var activateButton: UIButton = { let button = JXButton(type: .custom) button.leftAnyRightmargin = 13 @@ -36,9 +35,27 @@ class SPMineMemberNoView: UIView { button.layer.masksToBounds = true button.layer.borderWidth = 1 button.layer.borderColor = UIColor.colorFFD791().cgColor + button.backgroundColor = .color262014() return button }() + private lazy var textLabel1: UILabel = { + let label = UILabel() + label.font = .fontMedium(ofSize: 12) + label.textColor = .colorA69B89() + label.text = "Members can enjoy".localized + return label + }() + + private lazy var textLabel2: UILabel = { + let label = UILabel() + label.font = .fontMedium(ofSize: 12) + label.textColor = .colorFFD28F() + label.text = "Unlimited access to all series".localized + return label + }() + + override init(frame: CGRect) { super.init(frame: frame) _setupUI() @@ -56,6 +73,8 @@ extension SPMineMemberNoView { addSubview(iconImageView) addSubview(titleLabel) addSubview(activateButton) + addSubview(textLabel1) + addSubview(textLabel2) iconImageView.snp.makeConstraints { make in make.left.equalToSuperview().offset(12) @@ -73,6 +92,16 @@ extension SPMineMemberNoView { make.bottom.equalToSuperview().offset(-14) make.height.equalTo(28) } + + textLabel1.snp.makeConstraints { make in + make.left.equalToSuperview().offset(12) + make.bottom.equalTo(textLabel2.snp.top).offset(-kSPMainW(5)) + } + + textLabel2.snp.makeConstraints { make in + make.left.equalTo(textLabel1) + make.bottom.equalToSuperview().offset(-kSPMainW(12)) + } } } diff --git a/Thimra/Source/en.lproj/Localizable.strings b/Thimra/Source/en.lproj/Localizable.strings index a835210..1951c6f 100644 --- a/Thimra/Source/en.lproj/Localizable.strings +++ b/Thimra/Source/en.lproj/Localizable.strings @@ -53,6 +53,8 @@ "Log in" = "Log in"; "You are not a member yet" = "You are not a member yet"; "Activate" = "Activate"; +"Members can enjoy" = "Members can enjoy"; +"Unlimited access to all series" = "Unlimited access to all series"; "kLoginAgreementText" = "By continuing, you agree to the User Agreement and Privacy Policy"; diff --git a/Thimra/Thirdparty/ZKCycleScrollView-Swift/ZKCycleScrollView.swift b/Thimra/Thirdparty/ZKCycleScrollView-Swift/ZKCycleScrollView.swift index 267768c..88639c6 100644 --- a/Thimra/Thirdparty/ZKCycleScrollView-Swift/ZKCycleScrollView.swift +++ b/Thimra/Thirdparty/ZKCycleScrollView-Swift/ZKCycleScrollView.swift @@ -128,6 +128,20 @@ public enum ZKScrollDirection: Int { } } + ///item渐隐效果 + open var itemAlpha = false { + didSet { + flowLayout.itemAlpha = itemAlpha + } + } + + ///旋转角度 + open var rotationAngle = 0.0 { + didSet { + flowLayout.rotationAngle = rotationAngle + } + } + @IBInspectable open var hidesPageControl: Bool = false { didSet { pageControl?.isHidden = hidesPageControl diff --git a/Thimra/Thirdparty/ZKCycleScrollView-Swift/ZKCycleScrollViewFlowLayout.swift b/Thimra/Thirdparty/ZKCycleScrollView-Swift/ZKCycleScrollViewFlowLayout.swift index 4d71f00..80b947b 100644 --- a/Thimra/Thirdparty/ZKCycleScrollView-Swift/ZKCycleScrollViewFlowLayout.swift +++ b/Thimra/Thirdparty/ZKCycleScrollView-Swift/ZKCycleScrollViewFlowLayout.swift @@ -45,6 +45,10 @@ import UIKit open class ZKCycleScrollViewFlowLayout: UICollectionViewFlowLayout { open var zoomScale: CGFloat = 1.0 + ///item渐隐效果 + open var itemAlpha = false + ///旋转角度 + open var rotationAngle = 0.0 override open func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { return true @@ -74,19 +78,48 @@ open class ZKCycleScrollViewFlowLayout: UICollectionViewFlowLayout { default: let offset = collectionView.bounds.midX; let distanceForScale = itemSize.width + minimumLineSpacing; + for attr in attributes { var scale: CGFloat = 0.0; - let distance = abs(offset - attr.center.x) - if distance >= distanceForScale { + let distance = offset - attr.center.x + let abs_distance = abs(distance) + let screenScale = distance / (collectionView.bounds.width) + spLog(message: "++++++++++screenScale = \(screenScale), distanceForScale = \(distanceForScale), distance = \(abs_distance)") + + if abs_distance >= distanceForScale { scale = zoomScale; - } else if distance == 0.0 { + } else if abs_distance == 0.0 { scale = 1.0 attr.zIndex = 1 } else { - scale = zoomScale + (distanceForScale - distance) * (1.0 - zoomScale) / distanceForScale + scale = zoomScale + (distanceForScale - abs_distance) * (1.0 - zoomScale) / distanceForScale } - attr.transform = CGAffineTransform(scaleX: scale, y: scale) + + if itemAlpha { + var alpha = 1 - abs(screenScale) + if alpha < 0 { + alpha = 0 + } else if alpha > 1 { + alpha = 1 + } + attr.alpha = alpha + } else { + attr.alpha = 1 + } + //缩放 + let scaleTransform = CGAffineTransform(scaleX: scale, y: scale) + + //旋转 + let rotationAngle = kSPAngleToRadians(angle: -screenScale * self.rotationAngle) + let rotationTransform = CGAffineTransform(rotationAngle: rotationAngle) + +// attr.transform = CGAffineTransform(scaleX: scale, y: scale) + + // 组合旋转和缩放变换 + let combinedTransform = rotationTransform.concatenating(scaleTransform) + // 应用变换 + attr.transform = combinedTransform } } }