Advertisement
Guest User

Untitled

a guest
Mar 31st, 2020
123
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.78 KB | None | 0 0
  1. //
  2. // ViewController.swift
  3. // StackCollectionView
  4. //
  5. // Created by Krzysztof Babis on 20/03/2020.
  6. // Copyright © 2020 Krzysztof Babis. All rights reserved.
  7. //
  8.  
  9. import UIKit
  10. import SnapKit
  11.  
  12. class ViewController: UIViewController {
  13. private var collectionView: UICollectionView!
  14.  
  15. override func viewDidLoad() {
  16. super.viewDidLoad()
  17. initializeCollectionView()
  18. }
  19.  
  20. override func viewDidAppear(_ animated: Bool) {
  21. super.viewDidAppear(true)
  22. //collectionView.scrollToItem(at: IndexPath(item: 10, section: 0), at: .centeredVertically, animated: true)
  23. }
  24.  
  25. private func initializeCollectionView() {
  26. collectionView = UICollectionView(frame: .zero, collectionViewLayout: StickyCollectionViewFlowLayout())
  27. collectionView.backgroundColor = .yellow
  28. collectionView.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "cell")
  29. collectionView.dataSource = self
  30. collectionView.delegate = self
  31. view.addSubview(collectionView)
  32.  
  33. collectionView.snp.makeConstraints { (make) in
  34. make.left.right.bottom.equalTo(view.safeAreaLayoutGuide)
  35. make.height.equalToSuperview().multipliedBy(0.3)
  36. }
  37. }
  38. }
  39.  
  40. extension ViewController: UICollectionViewDelegateFlowLayout {
  41. func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
  42. return CGSize(width: UIScreen.main.bounds.width * 0.8, height: UIScreen.main.bounds.height * 0.25)
  43. }
  44. }
  45.  
  46. extension ViewController: UICollectionViewDataSource {
  47. func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
  48. return 10
  49. }
  50.  
  51. func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
  52. let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath)
  53. let label = UILabel(frame: cell.bounds)
  54. cell.layer.borderWidth = 2.0
  55. cell.layer.borderColor = UIColor.black.cgColor
  56. cell.backgroundColor = .red
  57. label.text = "\(indexPath.row)"
  58. label.textAlignment = .center
  59. cell.addSubview(label)
  60. return cell
  61. }
  62. }
  63.  
  64. final class StickyCollectionViewFlowLayout: UICollectionViewFlowLayout {
  65. private let overlap: CGFloat
  66. private let scaleMultiplier: CGFloat?
  67.  
  68. init(overlap: CGFloat = 10.0, scaleMultiplier: CGFloat = 0.06) {
  69. self.overlap = overlap
  70. self.scaleMultiplier = scaleMultiplier
  71. super.init()
  72. }
  73.  
  74. required init?(coder: NSCoder) {
  75. fatalError("init(coder:) has not been implemented")
  76. }
  77.  
  78. override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
  79. guard let superLayoutAttributes = super.layoutAttributesForElements(in: rect) else { return nil }
  80.  
  81. let items = NSArray(array: superLayoutAttributes, copyItems: true)
  82. var headerAttributes: UICollectionViewLayoutAttributes?
  83.  
  84. for item in items {
  85. guard let attributes = item as? UICollectionViewLayoutAttributes else { continue }
  86.  
  87. if attributes.representedElementKind == UICollectionView.elementKindSectionHeader {
  88. headerAttributes = attributes
  89. } else {
  90. self.updateCellAttributes(attributes, headerAttributes: headerAttributes)
  91. }
  92. }
  93.  
  94. return items as? [UICollectionViewLayoutAttributes]
  95. }
  96.  
  97. func updateCellAttributes(_ attributes: UICollectionViewLayoutAttributes, headerAttributes: UICollectionViewLayoutAttributes?) {
  98. guard let collectionView = collectionView else { return }
  99.  
  100. let minY = collectionView.bounds.minY + collectionView.contentInset.top
  101. var maxY = attributes.frame.origin.y
  102.  
  103. if let headerAttributes = headerAttributes {
  104. maxY -= headerAttributes.bounds.height
  105. }
  106.  
  107. let finalY = max(minY, maxY)
  108. var origin = attributes.frame.origin
  109.  
  110. if let scaleMultiplier = scaleMultiplier {
  111. let deltaY = (finalY - origin.y) / attributes.frame.height
  112. let scale = 1 - deltaY * scaleMultiplier
  113. attributes.transform = CGAffineTransform(scaleX: scale, y: scale)
  114. }
  115.  
  116. origin.y = finalY + CGFloat(attributes.indexPath.row) * overlap
  117. attributes.frame = CGRect(origin: origin, size: attributes.frame.size)
  118. attributes.zIndex = attributes.indexPath.row
  119. }
  120.  
  121. override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
  122. return true
  123. }
  124. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement