2016-08-16 66 views
2

你好我有工作collectionview自定义布局代码,但一些单元格我需要更改单元格中的单元格宽度动态地从json动态变量。Swift Collection查看单元格中的自定义布局更改单元格宽度

我CustomCollectionViewLayout

import UIKit 

public var CELL_HEIGHT = 22.0 
public var CELL_WIDTH = 40.0 // HERE WIDTH SOME CELLS MUST BE 80 

class CustomCollectionViewLayout: UICollectionViewLayout { 

    // Used for calculating each cells CGRect on screen. 
    // CGRect will define the Origin and Size of the cell. 

    let STATUS_BAR = UIApplication.sharedApplication().statusBarFrame.height 

    // Dictionary to hold the UICollectionViewLayoutAttributes for 
    // each cell. The layout attribtues will define the cell's size 
    // and position (x, y, and z index). I have found this process 
    // to be one of the heavier parts of the layout. I recommend 
    // holding onto this data after it has been calculated in either 
    // a dictionary or data store of some kind for a smooth performance. 
    var cellAttrsDictionary = Dictionary<NSIndexPath, UICollectionViewLayoutAttributes>() 

    // Defines the size of the area the user can move around in 
    // within the collection view. 
    var contentSize = CGSize.zero 

    // Used to determine if a data source update has occured. 
    // Note: The data source would be responsible for updating 
    // this value if an update was performed. 
    var dataSourceDidUpdate = true 

    override func collectionViewContentSize() -> CGSize { 
     return self.contentSize 
    } 

    override func prepareLayout() { 

     // Only update header cells. 
     if !dataSourceDidUpdate { 

      // Determine current content offsets. 
      let xOffset = collectionView!.contentOffset.x 
      let yOffset = collectionView!.contentOffset.y 

      if collectionView?.numberOfSections() > 0 { 
       for section in 0...collectionView!.numberOfSections()-1 { 

        // Confirm the section has items. 
        if collectionView?.numberOfItemsInSection(section) > 0 { 

         // Update all items in the first row. 
         if section == 0 { 
          for item in 0...collectionView!.numberOfItemsInSection(section)-1 { 

           // Build indexPath to get attributes from dictionary. 
           let indexPath = NSIndexPath(forItem: item, inSection: section) 

           // Update y-position to follow user. 
           if let attrs = cellAttrsDictionary[indexPath] { 
            var frame = attrs.frame 

            // Also update x-position for corner cell. 
            if item == 0 { 
             frame.origin.x = xOffset 
            } 

            frame.origin.y = yOffset 
            attrs.frame = frame 
           } 

          } 

          // For all other sections, we only need to update 
          // the x-position for the fist item. 
         } else { 

          // Build indexPath to get attributes from dictionary. 
          let indexPath = NSIndexPath(forItem: 0, inSection: section) 

          // Update y-position to follow user. 
          if let attrs = cellAttrsDictionary[indexPath] { 
           var frame = attrs.frame 
           frame.origin.x = xOffset 
           attrs.frame = frame 
          } 

         } 
        } 
       } 
      } 


      // Do not run attribute generation code 
      // unless data source has been updated. 
      return 
     } 

     // Acknowledge data source change, and disable for next time. 
     dataSourceDidUpdate = false 

     var maxItemInASection: Int? 

     // Cycle through each section of the data source. 
     if collectionView?.numberOfSections() > 0 { 
      for section in 0...collectionView!.numberOfSections()-1 { 

       // Cycle through each item in the section. 
       if collectionView?.numberOfItemsInSection(section) > 0 { 
        for item in 0...collectionView!.numberOfItemsInSection(section)-1 { 

         // Build the UICollectionVieLayoutAttributes for the cell. 
         let cellIndex = NSIndexPath(forItem: item, inSection: section) 
         let xPos = Double(item) * CELL_WIDTH 
         let yPos = Double(section) * CELL_HEIGHT 

         let cellAttributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: cellIndex) 
         cellAttributes.frame = CGRect(x: xPos, y: yPos, width: CELL_WIDTH, height: CELL_HEIGHT) 

         // Determine zIndex based on cell type. 
         if section == 0 && item == 0 { 
          cellAttributes.zIndex = 4 
         } else if section == 0 { 
          cellAttributes.zIndex = 3 
         } else if item == 0 { 
          cellAttributes.zIndex = 2 
         } else { 
          cellAttributes.zIndex = 1 
         } 

         // Save the attributes. 
         cellAttrsDictionary[cellIndex] = cellAttributes 

         if maxItemInASection < item { 
          maxItemInASection = item 
         } 

        } 
       } 

      } 
     } 

     // Update content size. 
     let contentWidth = Double(maxItemInASection ?? 0) * CELL_WIDTH 
     let contentHeight = Double(collectionView!.numberOfSections()) * CELL_HEIGHT 
     self.contentSize = CGSize(width: contentWidth, height: contentHeight) 

    } 

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? { 

     // Create an array to hold all elements found in our current view. 
     var attributesInRect = [UICollectionViewLayoutAttributes]() 

     // Check each element to see if it should be returned. 
     for cellAttributes in cellAttrsDictionary.values.elements { 
      if CGRectIntersectsRect(rect, cellAttributes.frame) { 
       attributesInRect.append(cellAttributes) 
      } 
     } 

     // Return list of elements. 
     return attributesInRect 
    } 

    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes? { 
     return cellAttrsDictionary[indexPath]! 
    } 

    override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool { 
     return true 
    } 

} 

在这里,我的手机密码。

func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell { 
     let cell = collectionView.dequeueReusableCellWithReuseIdentifier("customCell", forIndexPath: indexPath) as! CustomCollectionViewCell 

    if items[indexPath.section].base == 2 { 

       cell.label.text = items[indexPath.section].base 


      cell.frame.size.width = 80 
      cell.layer.frame.size.width = 80 

      CELL_WIDTH = 80.0 // HERE I CHANGED SOME CELLS WIDTH 80 BUT DONT CHANGE THEM !! 

}else{ 

    cell.label.text = items[indexPath.section].base 



} 

你可以看到正面

CELL_WIDTH = 80.0 //这里,我改变了一些细胞宽度80,但不改变他们!

+0

任何创意的演示项目?我工作,但我没有解决这个问题约2天。 – SwiftDeveloper

回答

2

sizeForItemAtIndexPath对于UICollectionViewLayout不存在。所以你的CustomCollectionViewLayout继承自UICollectionViewLayout没有协议。您可以创建一个 widthForItemAtIndexPath方法。

protocol CustomCollectionViewDelegateLayout: NSObjectProtocol { 

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, widthForItemAtIndexPath indexPath: NSIndexPath) -> CGFloat 
} 

在你的viewController实现了这个协议方法。返回值将是给定的indexPath

extension CustomCollectionViewController: CustomCollectionViewDelegateLayout { 

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, widthForItemAtIndexPath indexPath: NSIndexPath) -> CGFloat { 

     //from indexPath.section and indexPath.item identify double width item 
     if sirano == 2 && satimdurum == 0 { 
      return regularWidth * 2 
     } 
     return regularWidth 
    } 
} 

宽度在你CustomCollectionViewLayout每次需要检查哪些项目应该是双项就可以计算出位置的prepareLayout()方法。

guard let width = delegate?.collectionView(collectionView!, layout: self, widthForItemAtIndexPath: cellIndex) else { 
         print("Please comform to CustomCollectionViewDelegateLayout protocol") 
         return 
        } 

制造和Xcode 7.2在这里https://github.com/rishi420/UICollectionviewsample

+0

TY男人工作! – SwiftDeveloper

3

您可以实现collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath)而不是继承UICollectionViewLayout - 除非您有其他原因这样做。

它会去有点像:

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { 

    if indexPath.item % 3 == 0 { // <-- your condition here 
     return CGSize(width: 40, height: 22) 
    } 
    return CGSize(width: 80, height: 22) 

} 

顺便说一句,不要忘记设置您的CollectionView的委托,以便将调用此方法。

修订

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize { 
    if items[indexPath.section].base == 2 { 
     return CGSize(width: 80, height: 22) 
    } else { 
     return CGSize(width: 44, height: 22) 
    } 
} 

这是我觉得你的方法应该是这样。 在你的cellForItem你只需要担心设置标签,让上面的代码照顾细胞的大小。

+0

感谢您的答案,但我在我的viewcontroller里面添加了你的代码,但是不工作,当json值= 2时,从json提交的项目[indexPath.section] .base将做宽度* 2的单元格。标签宽度 – SwiftDeveloper

+0

我需要在内部使用宽度* 2代码 - > func collectionView(collectionView:UICollectionView,cellForItemAtIndexPath indexPath:NSIndexPath) - > UICollectionViewCell {}我认为如果json的值... – SwiftDeveloper

+0

我的建议是给你使用'collectionView(collectionView:UICollectionView,布局collectionViewLayout:UICollectionViewLayout,sizeForItemAtIndexPath indexPath:NSIndexPath)'方法**而不是**实现UICollectionViewLayout子类。只需在答案中添加代码就行不通。你将不得不在你的方法内替换你的条件和适当的大小。 –

1

不要更改cellForItemAtIndexPath方法内的单元大小。单元布局已经在dequeueReusableCellWithReuseIdentifier之后设置。

将其更改为sizeForItemAtIndexPath。这在上面的委托方法之前被调用。

相关问题