banner优化

This commit is contained in:
zeng 2025-04-27 10:37:08 +08:00
parent cf398971db
commit 93a8ea36c1
8 changed files with 128 additions and 127 deletions

View File

@ -212,5 +212,17 @@ extension UIColor {
static func colorFFD791(alpha: CGFloat = 1) -> UIColor { static func colorFFD791(alpha: CGFloat = 1) -> UIColor {
return color(hex: 0xFFD791, alpha: alpha) 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)
}
} }

View File

@ -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
}
}

View File

@ -50,21 +50,17 @@ class SPHomeHeaderView: UICollectionReusableView {
return view return view
}() }()
private lazy var bannerLayout: SPZoomCollectionViewLayout = { private lazy var bannerView: ZKCycleScrollView = {
let layout = SPZoomCollectionViewLayout() let view = ZKCycleScrollView(frame: .zero, shouldInfiniteLoop: true)
layout.itemSize = .init(width: 234, height: Self.bannerHeight()) view.itemSize = .init(width: 234, height: Self.bannerHeight())
layout.minimumLineSpacing = 10 view.itemAlpha = true
layout.minimumInteritemSpacing = 0 view.itemZoomScale = 0.9
return layout view.itemSpacing = 10
}() view.rotationAngle = 5
private lazy var bannerView: SPCollectionView = {
let view = SPCollectionView(frame: .zero, collectionViewLayout: bannerLayout)
view.delegate = self view.delegate = self
view.dataSource = self view.dataSource = self
view.showsVerticalScrollIndicator = false view.hidesPageControl = true
view.showsHorizontalScrollIndicator = false view.register(SPHomeZoomBannerCell.self, forCellWithReuseIdentifier: "banner")
SPHomeZoomBannerCell.registerCell(collectionView: view)
view.snp.makeConstraints { make in view.snp.makeConstraints { make in
make.width.equalTo(kSPScreenWidth) 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 { extension SPHomeHeaderView {

View File

@ -7,7 +7,7 @@
import UIKit import UIKit
class SPHomeZoomBannerCell: SPCollectionViewCell { class SPHomeZoomBannerCell: ZKCycleScrollViewCell {
var model: SPShortModel? { var model: SPShortModel? {
didSet { didSet {

View File

@ -25,7 +25,6 @@ class SPMineMemberNoView: UIView {
return label return label
}() }()
private lazy var activateButton: UIButton = { private lazy var activateButton: UIButton = {
let button = JXButton(type: .custom) let button = JXButton(type: .custom)
button.leftAnyRightmargin = 13 button.leftAnyRightmargin = 13
@ -36,9 +35,27 @@ class SPMineMemberNoView: UIView {
button.layer.masksToBounds = true button.layer.masksToBounds = true
button.layer.borderWidth = 1 button.layer.borderWidth = 1
button.layer.borderColor = UIColor.colorFFD791().cgColor button.layer.borderColor = UIColor.colorFFD791().cgColor
button.backgroundColor = .color262014()
return button 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) { override init(frame: CGRect) {
super.init(frame: frame) super.init(frame: frame)
_setupUI() _setupUI()
@ -56,6 +73,8 @@ extension SPMineMemberNoView {
addSubview(iconImageView) addSubview(iconImageView)
addSubview(titleLabel) addSubview(titleLabel)
addSubview(activateButton) addSubview(activateButton)
addSubview(textLabel1)
addSubview(textLabel2)
iconImageView.snp.makeConstraints { make in iconImageView.snp.makeConstraints { make in
make.left.equalToSuperview().offset(12) make.left.equalToSuperview().offset(12)
@ -73,6 +92,16 @@ extension SPMineMemberNoView {
make.bottom.equalToSuperview().offset(-14) make.bottom.equalToSuperview().offset(-14)
make.height.equalTo(28) 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))
}
} }
} }

View File

@ -53,6 +53,8 @@
"Log in" = "Log in"; "Log in" = "Log in";
"You are not a member yet" = "You are not a member yet"; "You are not a member yet" = "You are not a member yet";
"Activate" = "Activate"; "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"; "kLoginAgreementText" = "By continuing, you agree to the User Agreement and Privacy Policy";

View File

@ -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 { @IBInspectable open var hidesPageControl: Bool = false {
didSet { didSet {
pageControl?.isHidden = hidesPageControl pageControl?.isHidden = hidesPageControl

View File

@ -45,6 +45,10 @@ import UIKit
open class ZKCycleScrollViewFlowLayout: UICollectionViewFlowLayout { open class ZKCycleScrollViewFlowLayout: UICollectionViewFlowLayout {
open var zoomScale: CGFloat = 1.0 open var zoomScale: CGFloat = 1.0
///item
open var itemAlpha = false
///
open var rotationAngle = 0.0
override open func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool { override open func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
return true return true
@ -74,19 +78,48 @@ open class ZKCycleScrollViewFlowLayout: UICollectionViewFlowLayout {
default: default:
let offset = collectionView.bounds.midX; let offset = collectionView.bounds.midX;
let distanceForScale = itemSize.width + minimumLineSpacing; let distanceForScale = itemSize.width + minimumLineSpacing;
for attr in attributes { for attr in attributes {
var scale: CGFloat = 0.0; var scale: CGFloat = 0.0;
let distance = abs(offset - attr.center.x) let distance = offset - attr.center.x
if distance >= distanceForScale { 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; scale = zoomScale;
} else if distance == 0.0 { } else if abs_distance == 0.0 {
scale = 1.0 scale = 1.0
attr.zIndex = 1 attr.zIndex = 1
} else { } 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
} }
} }
} }