|
@@ -4,183 +4,86 @@
|
|
|
//
|
|
|
// Created by 100Years on 2025/4/7.
|
|
|
//
|
|
|
-class CustomHorizontalPageLayout: UICollectionViewFlowLayout {
|
|
|
-
|
|
|
- // MARK: - 可配置属性
|
|
|
-
|
|
|
- /// 每页行数(默认2行)
|
|
|
- var rowsPerPage: Int = 2 {
|
|
|
- didSet { invalidateLayout() }
|
|
|
- }
|
|
|
-
|
|
|
- /// 每页列数(默认4列)
|
|
|
- var columnsPerPage: Int = 4 {
|
|
|
- didSet { invalidateLayout() }
|
|
|
- }
|
|
|
-
|
|
|
- /// 是否启用Z字形排列(默认开启)
|
|
|
- var isZLayoutEnabled: Bool = true {
|
|
|
- didSet { invalidateLayout() }
|
|
|
- }
|
|
|
-
|
|
|
- /// 每页单元格数量(自动计算)
|
|
|
- private var itemsPerPage: Int {
|
|
|
- rowsPerPage * columnsPerPage
|
|
|
- }
|
|
|
-
|
|
|
- // MARK: - 布局计算
|
|
|
-
|
|
|
- override var collectionViewContentSize: CGSize {
|
|
|
- guard let collectionView = collectionView else { return .zero }
|
|
|
-
|
|
|
- let itemCount = CGFloat(collectionView.numberOfItems(inSection: 0))
|
|
|
- let pageCount = ceil(itemCount / CGFloat(itemsPerPage))
|
|
|
- return CGSize(
|
|
|
- width: collectionView.bounds.width * pageCount,
|
|
|
- height: collectionView.bounds.height
|
|
|
- )
|
|
|
- }
|
|
|
-
|
|
|
- override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
|
|
|
- guard let collectionView = collectionView else { return nil }
|
|
|
-
|
|
|
- return (0..<collectionView.numberOfItems(inSection: 0)).compactMap {
|
|
|
- layoutAttributesForItem(at: IndexPath(item: $0, section: 0))
|
|
|
- }.filter { rect.intersects($0.frame) }
|
|
|
- }
|
|
|
-
|
|
|
- override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
|
|
|
- guard let collectionView = collectionView else { return nil }
|
|
|
-
|
|
|
- let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
|
|
|
-
|
|
|
- // 计算页面信息
|
|
|
- let pageWidth = collectionView.bounds.width
|
|
|
- let pageIndex = indexPath.item / itemsPerPage
|
|
|
- let itemInPage = indexPath.item % itemsPerPage
|
|
|
-
|
|
|
- // 计算单元格行列位置
|
|
|
- let (row, column) = positionForItem(itemInPage)
|
|
|
-
|
|
|
- // 计算单元格尺寸
|
|
|
- let itemWidth = (pageWidth - sectionInset.left - sectionInset.right -
|
|
|
- CGFloat(columnsPerPage - 1) * minimumInteritemSpacing) / CGFloat(columnsPerPage)
|
|
|
- let itemHeight = (collectionView.bounds.height - sectionInset.top - sectionInset.bottom -
|
|
|
- CGFloat(rowsPerPage - 1) * minimumLineSpacing) / CGFloat(rowsPerPage)
|
|
|
-
|
|
|
- // 计算位置坐标
|
|
|
- let x = sectionInset.left + CGFloat(column) * (itemWidth + minimumInteritemSpacing) +
|
|
|
- CGFloat(pageIndex) * pageWidth
|
|
|
- let y = sectionInset.top + CGFloat(row) * (itemHeight + minimumLineSpacing)
|
|
|
-
|
|
|
- attributes.frame = CGRect(x: x, y: y, width: itemWidth, height: itemHeight)
|
|
|
- return attributes
|
|
|
- }
|
|
|
-
|
|
|
- // MARK: - 行列位置计算
|
|
|
- private func positionForItem(_ itemInPage: Int) -> (row: Int, column: Int) {
|
|
|
- if isZLayoutEnabled {
|
|
|
- // Z字形排列(从左到右,从上到下)
|
|
|
- let row = itemInPage / columnsPerPage
|
|
|
- let column = itemInPage % columnsPerPage
|
|
|
- return (row, column)
|
|
|
- } else {
|
|
|
- // 垂直排列(从上到下,从左到右)
|
|
|
- let column = itemInPage / rowsPerPage
|
|
|
- let row = itemInPage % rowsPerPage
|
|
|
- return (row, column)
|
|
|
- }
|
|
|
- }
|
|
|
-}
|
|
|
-//class CustomHorizontalPageLayout: UICollectionViewFlowLayout {
|
|
|
+//class ContinuousHorizontalLayout: UICollectionViewFlowLayout {
|
|
|
//
|
|
|
-// // 每页显示的单元格数量(2行4列)
|
|
|
-// private let itemsPerPage = 8
|
|
|
+// // 缓存布局属性
|
|
|
+// private var cachedAttributes: [UICollectionViewLayoutAttributes] = []
|
|
|
+// private var contentWidth: CGFloat = 0
|
|
|
//
|
|
|
-// // 准备布局
|
|
|
// override func prepare() {
|
|
|
// super.prepare()
|
|
|
-// setupLayout()
|
|
|
+// guard let collectionView = collectionView else { return }
|
|
|
+//
|
|
|
+// resetCache()
|
|
|
+// calculateItemsLayout(collectionView)
|
|
|
// }
|
|
|
//
|
|
|
-// private func setupLayout() {
|
|
|
-// scrollDirection = .horizontal
|
|
|
-// minimumLineSpacing = 0
|
|
|
-// minimumInteritemSpacing = 0
|
|
|
+// private func resetCache() {
|
|
|
+// cachedAttributes.removeAll()
|
|
|
+// contentWidth = 0
|
|
|
// }
|
|
|
//
|
|
|
-// override var collectionViewContentSize: CGSize {
|
|
|
-// guard let collectionView = collectionView else { return .zero }
|
|
|
-//
|
|
|
-// // 关键修改:使用浮点数计算总页数(向上取整)
|
|
|
-// let totalItems = CGFloat(collectionView.numberOfItems(inSection: 0))
|
|
|
-// let pageCount = ceil(totalItems / CGFloat(itemsPerPage))
|
|
|
-//
|
|
|
-// return CGSize(
|
|
|
-// width: collectionView.bounds.width * pageCount,
|
|
|
-// height: collectionView.bounds.height
|
|
|
-// )
|
|
|
-// }
|
|
|
-//
|
|
|
-// // 布局属性计算
|
|
|
-// override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
|
|
|
-// guard let collectionView = collectionView else { return nil }
|
|
|
+// private func calculateItemsLayout(_ collectionView: UICollectionView) {
|
|
|
+// let itemCount = collectionView.numberOfItems(inSection: 0)
|
|
|
+// guard itemCount > 0 else { return }
|
|
|
//
|
|
|
-// var allAttributes: [UICollectionViewLayoutAttributes] = []
|
|
|
-// let totalItems = collectionView.numberOfItems(inSection: 0)
|
|
|
+// var currentX: CGFloat = sectionInset.left
|
|
|
+// var currentY: CGFloat = sectionInset.top
|
|
|
+// var rowMaxHeight: CGFloat = 0
|
|
|
//
|
|
|
-// for item in 0..<totalItems {
|
|
|
+// for item in 0..<itemCount {
|
|
|
// let indexPath = IndexPath(item: item, section: 0)
|
|
|
-// if let attributes = layoutAttributesForItem(at: indexPath) {
|
|
|
-// if rect.intersects(attributes.frame) {
|
|
|
-// allAttributes.append(attributes)
|
|
|
-// }
|
|
|
+// let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
|
|
|
+//
|
|
|
+// // 计算当前行剩余空间
|
|
|
+// let remainingWidth = collectionView.bounds.width - currentX - sectionInset.right
|
|
|
+// let itemRequiredWidth = itemSize.width + (item == 0 ? 0 : minimumInteritemSpacing)
|
|
|
+//
|
|
|
+// // 换行判断
|
|
|
+// if remainingWidth < itemRequiredWidth {
|
|
|
+// currentX = sectionInset.left
|
|
|
+// currentY += rowMaxHeight + minimumLineSpacing
|
|
|
+// rowMaxHeight = 0
|
|
|
// }
|
|
|
+//
|
|
|
+// // 设置位置坐标
|
|
|
+// attributes.frame = CGRect(
|
|
|
+// x: currentX + (item == 0 ? 0 : minimumInteritemSpacing),
|
|
|
+// y: currentY,
|
|
|
+// width: itemSize.width,
|
|
|
+// height: itemSize.height
|
|
|
+// )
|
|
|
+//
|
|
|
+// // 更新布局跟踪参数
|
|
|
+// currentX = attributes.frame.maxX
|
|
|
+// rowMaxHeight = max(rowMaxHeight, itemSize.height)
|
|
|
+// contentWidth = max(contentWidth, attributes.frame.maxX + sectionInset.right)
|
|
|
+//
|
|
|
+// cachedAttributes.append(attributes)
|
|
|
// }
|
|
|
-// return allAttributes
|
|
|
// }
|
|
|
//
|
|
|
-// override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
|
|
|
-// guard let collectionView = collectionView else { return nil }
|
|
|
-//
|
|
|
-// let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath)
|
|
|
-//
|
|
|
-// // 原始页面计算逻辑保持不变
|
|
|
-// let page = indexPath.item / itemsPerPage
|
|
|
-// let itemInPage = indexPath.item % itemsPerPage
|
|
|
-//
|
|
|
-// // 原始行列计算保持不变
|
|
|
-// let row: Int
|
|
|
-// let column: Int
|
|
|
-// if itemInPage < 4 {
|
|
|
-// row = 0
|
|
|
-// column = itemInPage
|
|
|
-// } else {
|
|
|
-// row = 1
|
|
|
-// column = itemInPage - 4
|
|
|
-// }
|
|
|
-//
|
|
|
-// // 原始尺寸计算保持不变
|
|
|
-// let pageWidth = collectionView.bounds.width
|
|
|
-// let itemWidth = (pageWidth - sectionInset.left - sectionInset.right) / 4
|
|
|
-// let itemHeight = (collectionView.bounds.height - sectionInset.top - sectionInset.bottom) / 2
|
|
|
-//
|
|
|
-// // 原始位置计算保持不变
|
|
|
-// let x = sectionInset.left + CGFloat(column) * itemWidth + CGFloat(page) * pageWidth
|
|
|
-// let y = sectionInset.top + CGFloat(row) * itemHeight
|
|
|
-//
|
|
|
-// attributes.frame = CGRect(
|
|
|
-// x: x,
|
|
|
-// y: y,
|
|
|
-// width: itemWidth,
|
|
|
-// height: itemHeight
|
|
|
-// )
|
|
|
-//
|
|
|
-// return attributes
|
|
|
-// }
|
|
|
+// override var collectionViewContentSize: CGSize {
|
|
|
+// guard let collectionView = collectionView else { return .zero }
|
|
|
+// return CGSize(
|
|
|
+// width: contentWidth,
|
|
|
+// height: collectionView.bounds.height
|
|
|
+// )
|
|
|
+// }
|
|
|
+//
|
|
|
+// override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
|
|
|
+// return cachedAttributes.filter { rect.intersects($0.frame) }
|
|
|
+// }
|
|
|
+//
|
|
|
+// override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
|
|
|
+// return cachedAttributes.first { $0.indexPath == indexPath }
|
|
|
+// }
|
|
|
//
|
|
|
+// override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
|
|
|
+// guard let oldBounds = collectionView?.bounds else { return false }
|
|
|
+// return oldBounds.width != newBounds.width
|
|
|
+// }
|
|
|
//}
|
|
|
-
|
|
|
class TSPTPSelectStyleView: TSBaseView {
|
|
|
var cellH: CGFloat = 108.0
|
|
|
lazy var viewH: CGFloat = cellH*2+4.0
|
|
@@ -195,12 +98,14 @@ class TSPTPSelectStyleView: TSBaseView {
|
|
|
|
|
|
var clickHandle: ((IndexPath, TSGenerateStyleModel) -> Void)?
|
|
|
|
|
|
- lazy var layout: CustomHorizontalPageLayout = {
|
|
|
- let layout = CustomHorizontalPageLayout()
|
|
|
+ lazy var layout: UICollectionViewFlowLayout = {
|
|
|
+ let layout = UICollectionViewFlowLayout()
|
|
|
layout.scrollDirection = .horizontal
|
|
|
layout.sectionInset = UIEdgeInsets(top: 0, left: 16, bottom: 0, right: 16)
|
|
|
layout.minimumLineSpacing = 4
|
|
|
- layout.minimumInteritemSpacing = 0
|
|
|
+ layout.minimumInteritemSpacing = 4
|
|
|
+ let w = (k_ScreenWidth - 32.0 - 30.0 - 2.0) / 4.0
|
|
|
+ layout.itemSize = CGSize(width: w, height: cellH)
|
|
|
return layout
|
|
|
}()
|
|
|
|
|
@@ -208,7 +113,7 @@ class TSPTPSelectStyleView: TSBaseView {
|
|
|
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
|
|
|
collectionView.delegate = self
|
|
|
collectionView.dataSource = self
|
|
|
- collectionView.isPagingEnabled = true
|
|
|
+// collectionView.isPagingEnabled = true
|
|
|
collectionView.showsVerticalScrollIndicator = false
|
|
|
collectionView.showsHorizontalScrollIndicator = false
|
|
|
collectionView.backgroundColor = .clear
|