Advertisement
Guest User

Custom Collection View Layout

a guest
Aug 24th, 2016
81
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Swift 7.03 KB | None | 0 0
  1. import UIKit
  2.  
  3. class CustomCollectionViewLayout: UICollectionViewLayout {
  4.  
  5.     // Used for calculating each cells CGRect on screen.
  6.     // CGRect will define the Origin and Size of the cell.
  7.     let cellHeight = 30.0
  8.     let cellWidth = 100.0
  9.     let statusBar = UIApplication.shared().statusBarFrame.height
  10.    
  11.     // Dictionary to hold the UICollectionViewLayoutAttributes for
  12.     // each cell. The layout attribtues will define the cell's size
  13.     // and position (x, y, and z index). I have found this process
  14.     // to be one of the heavier parts of the layout. I recommend
  15.     // holding onto this data after it has been calculated in either
  16.     // a dictionary or data store of some kind for a smooth performance.
  17.     var cellAttrDictionary = Dictionary<NSIndexPath, UICollectionViewLayoutAttributes>()
  18.  
  19.     // Defines the size of the area the user can move around in
  20.     // within the collection view.
  21.     var contentSize = CGSize.zero
  22.    
  23.     // Used to determine if a data source update has occured.
  24.     // Note: The data source would be responsible for updating
  25.     // this value if an update was performed.
  26.     var dataSourceDidUpdate = true
  27.    
  28.    
  29.     override func collectionViewContentSize() -> CGSize {
  30.        
  31.         return self.contentSize
  32.     }
  33.    
  34.     override func prepare() {
  35.        
  36.         // Only update header cells.
  37.         if !dataSourceDidUpdate {
  38.            
  39.             // Determine current content offsets.
  40.             let xOffset = collectionView!.contentOffset.x
  41.             let yOffset = collectionView!.contentOffset.y
  42.            
  43.             if collectionView?.numberOfSections() > 0 {
  44.                 for section in 0...collectionView!.numberOfSections()-1 {
  45.                    
  46.                     // Confirm the section has items.
  47.                     if collectionView?.numberOfItems(inSection: section) > 0 {
  48.                        
  49.                         // Update all items in the first row.
  50.                         if section == 0 {
  51.                            
  52.                             for item in 0...collectionView!.numberOfItems(inSection: section)-1 {
  53.                                
  54.                                 // Build indexPath to get attributes from dictionary.
  55.                                 let indexPath = NSIndexPath(item: item, section: section)
  56.                                
  57.                                 // Update y-position to follow user.
  58.                                 if let attrs = cellAttrDictionary[indexPath] {
  59.                                    
  60.                                     var frame = attrs.frame
  61.                                    
  62.                                     // Also update x-position for corner cell.
  63.                                     if item == 0 {
  64.                                         frame.origin.x = xOffset
  65.                                     }
  66.    
  67.                                     frame.origin.y = yOffset
  68.                                     attrs.frame = frame
  69.                                 }
  70.                             }
  71.                            
  72.                             // For all other sections, we only need to update
  73.                             // the x-position for the fist item.
  74.                         } else {
  75.                            
  76.                             // Build indexPath to get attributes from dictionary.
  77.                             let indexPath = NSIndexPath(item: 0, section: section)
  78.                            
  79.                             // Update y-position to follow user.
  80.                             if let attrs = cellAttrDictionary[indexPath] {
  81.                                 var frame = attrs.frame
  82.                                 frame.origin.x = xOffset
  83.                                 attrs.frame = frame
  84.                             }
  85.                         }
  86.                     }
  87.                 }
  88.             }
  89.            
  90.            
  91.             // Do not run attribute generation code
  92.             // unless data source has been updated.
  93.             return
  94.         }
  95.        
  96.         // Acknowledge data source change, and disable for next time.
  97.         dataSourceDidUpdate = false
  98.        
  99.         if self.collectionView?.numberOfSections() > 0 {
  100.        
  101.             for section in 0...collectionView!.numberOfSections()-1 {
  102.                
  103.                 if collectionView?.numberOfItems(inSection: section) > 0 {
  104.                    
  105.                     for item in 0...collectionView!.numberOfItems(inSection: section)-1 {
  106.                        
  107.                         // Build the UICollectionVieLayoutAttributes for the cell.
  108.                         let cellIndex = NSIndexPath(item: item, section: section)
  109.                         let xPos = Double(item) * cellWidth
  110.                         let yPos = Double(section) * cellHeight
  111.                        
  112.                         let cellAttributes = UICollectionViewLayoutAttributes(forCellWith: cellIndex as IndexPath)
  113.                         cellAttributes.frame = CGRect(x: xPos, y: yPos, width: cellWidth, height: cellHeight)
  114.                        
  115.                         // Determine zIndex based on cell type.
  116.                         if section == 0 && item == 0 {
  117.                             cellAttributes.zIndex = 4
  118.                         } else if section == 0 {
  119.                             cellAttributes.zIndex = 3
  120.                         } else if item == 0 {
  121.                             cellAttributes.zIndex = 2
  122.                         } else {
  123.                             cellAttributes.zIndex = 1
  124.                         }
  125.                        
  126.                         // Save the attributes.
  127.                         cellAttrDictionary[cellIndex] = cellAttributes
  128.                     }
  129.                 }
  130.             }
  131.         }
  132.        
  133.         // Update content size.
  134.         let contentWidth = Double(collectionView!.numberOfItems(inSection: 0)) * cellWidth
  135.         let contentHeight = Double(collectionView!.numberOfSections()) * cellHeight
  136.         self.contentSize = CGSize(width: contentWidth, height: contentHeight)
  137.     }
  138.    
  139.     override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
  140.  
  141.         // Create an array to hold all elements found in our current view.
  142.         var attributesInRect = [UICollectionViewLayoutAttributes]()
  143.        
  144.         // Check each element to see if it should be returned.
  145.         for cellAttributes in cellAttrDictionary.values {
  146.            
  147.             if rect.intersects(cellAttributes.frame) {
  148.                
  149.                 attributesInRect.append(cellAttributes)
  150.             }
  151.         }
  152.        
  153.         // Return list of elements.
  154.         return attributesInRect
  155.  
  156.        
  157.     }
  158.    
  159.     override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
  160.         return cellAttrDictionary[indexPath]!
  161.     }
  162.    
  163.     override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
  164.         return true
  165.     }
  166. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement