4

我有一個任務,我必須準備一個簡單的GridView,只有很少的約束。我想到了使用UICollectionView,並在網上做了一些研究。我發現了一篇博客文章here,它做了我希望實現的類似功能。如何使用SWIFT以編程方式設置UICollectionViewCell大小,取決於其中的UIlabel的動態大小?

現在,它使用行類&列。每個單元格中都有一個UILabel。因此,該UILabel可以具有動態文本,因此該單元應根據UILabel的動態調整其大小。

請在下面找到所有的代碼 -

UICollectionView爲行單元格

class RowCell: UICollectionViewCell 
{ 
    var textLabel : UILabel! 

    override init(frame: CGRect) 
    { 
     super.init(frame: frame) 

     textLabel = UILabel(frame: CGRectMake(0, 0, 65, 35)) 
     textLabel.font = UIFont.systemFontOfSize(UIFont.smallSystemFontSize()) 
     textLabel.textAlignment = .Center 
     textLabel.numberOfLines = 0 
     textLabel.backgroundColor = UIColor.clearColor() 
     textLabel.lineBreakMode = NSLineBreakMode.ByCharWrapping 
     textLabel.sizeThatFits(CGSizeMake(self.bounds.width, self.bounds.height)) 

     contentView.addSubview(textLabel) 
     self.layer.borderWidth = 0.7 
     self.layer.borderColor = charcoalColor.CGColor 
     self.frame = CGRectMake(frame.origin.x, frame.origin.y, textLabel.frame.width*8, textLabel.frame.height*8) 

    } 

    required init(coder aDecoder: NSCoder) { 
     fatalError("init(coder:) has not been implemented") 
    } 
} 

UICollectionView爲列單元

class ColumnCell: UICollectionViewCell 
{ 
    var columnLabel : UILabel! 

    override init(frame: CGRect) 
    { 
     super.init(frame: frame) 

     columnLabel = UILabel() 
     columnLabel.frame = CGRectMake(0 ,0 ,65 ,35) 
     columnLabel.font = UIFont.systemFontOfSize(UIFont.smallSystemFontSize()) 
     columnLabel.textAlignment = .Center 
     columnLabel.backgroundColor = UIColor.clearColor() 
     columnLabel.numberOfLines = 0 
     columnLabel.lineBreakMode = NSLineBreakMode.ByCharWrapping 
     columnLabel.sizeThatFits(CGSizeMake(self.bounds.width, self.bounds.height)) 


     contentView.addSubview(columnLabel) 

     self.layer.borderWidth = 0.7 
     self.layer.borderColor = charcoalColor.CGColor 

     self.frame = CGRectMake(frame.origin.x, frame.origin.y, columnLabel.frame.width*8, columnLabel.frame.height*8) 

    } 


    func getDynamicHeight(ofLabel label: UILabel)->CGFloat 
    { 
     if(label.text == nil) 
     { 
     label.sizeToFit() 
     var maxLabelSize = CGSizeMake(label.bounds.size.width, CGFloat(MAXFLOAT)) 
     var expectedSize = (label.text! as NSString).boundingRectWithSize(maxLabelSize, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName:label.font], context: nil).size 

     return expectedSize.height 
     } 

     return CGFloat(30) 

    } 


    required init(coder aDecoder: NSCoder) 
    { 
     fatalError("init(coder:) has not been implemented") 
    } 

} 

我的視圖控制器中,我創建的CollectionView

class ViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate 
{ 

    let columnCellIdentifier = "ColumnCellIdentifier" 
    let rowCellIdentifier = "RowCellIdentifier" 
    let arrayOfData = ["Tom", "Han", "Jerry", "Popye", "Bluto", "Elvis", "Vin", "PaulShankar Dharmawat", "Vishwanathan", "Belloweiss" ] 
    var collectionView: UICollectionView! 

    override func viewDidLoad() 
    { 
     super.viewDidLoad() 
     self.view.backgroundColor = UIColor.whiteColor() 

     collectionView = UICollectionView(frame: CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y + 20.0, self.view.frame.size.width, self.view.frame.size.height), collectionViewLayout: CustomCollectionViewLayout()) 

     self.collectionView.delegate = self  // delegate : UICollectionViewDelegate 
     self.collectionView.dataSource = self // datasource : UICollectionViewDataSource 

     self.collectionView.registerClass(ColumnCell.self, forCellWithReuseIdentifier: columnCellIdentifier) 
     self.collectionView.registerClass(RowCell.self, forCellWithReuseIdentifier: rowCellIdentifier) 
     self.collectionView.backgroundColor = UIColor.whiteColor() 

     self.view.addSubview(self.collectionView) 


    } 

    override func didReceiveMemoryWarning() 
    { 
     super.didReceiveMemoryWarning() 
    } 

    // MARK - UICollectionViewDataSource Methods 

    // This is number of rows that we want in table 
    func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int 
    { 
     return 20 
    } 

    // This is number of columns that we want in table 
    func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    { 
     return 20 
    } 

    func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 
    { 

     if indexPath.section == 0 
     { 
      if indexPath.row == 0 
      { 
       let columnCell : ColumnCell = collectionView.dequeueReusableCellWithReuseIdentifier(columnCellIdentifier, forIndexPath: indexPath) as! ColumnCell 
       columnCell.columnLabel.text = "⬇️ DATE/NAMES➡️" 

       return columnCell 

      } 
      else 
      { 
       // First Section -> row data 

       let rowCell : RowCell = collectionView .dequeueReusableCellWithReuseIdentifier(rowCellIdentifier, forIndexPath: indexPath) as! RowCell 

       if(indexPath.row < arrayOfData.count) 
       { 
        rowCell.textLabel.text = "\(arrayOfData[indexPath.row])" 
       } 
       else 
       { 
        rowCell.textLabel.text = "\([indexPath.section]),\([indexPath.row])" 
       } 

       if indexPath.section % 2 != 0 
       { 
        rowCell.backgroundColor = limeYellowColor 
       } 
       else 
       { 
        rowCell.backgroundColor = UIColor.whiteColor() 
       } 

       return rowCell 
      } 
     } 
     else 
     { 
      if indexPath.row == 0 
      { 
       let columnCell : ColumnCell = collectionView .dequeueReusableCellWithReuseIdentifier(columnCellIdentifier, forIndexPath: indexPath) as! ColumnCell 

       columnCell.columnLabel.text = "\(indexPath.section),\(indexPath.row)" 

       if indexPath.section % 2 != 0 
       { 
         columnCell.backgroundColor = limeYellowColor 
       } 
       else 
       { 
        columnCell.backgroundColor = UIColor.whiteColor() 
       } 

       return columnCell 
      } 
      else 
      { 
       let rowCell : RowCell = collectionView .dequeueReusableCellWithReuseIdentifier(rowCellIdentifier, forIndexPath: indexPath) as! RowCell 
       rowCell.textLabel.text = "I am a rockstar yo yo baby" 

       if indexPath.section % 2 != 0 
       { 
        rowCell.backgroundColor = limeYellowColor 
       } 
       else 
       { 
        rowCell.backgroundColor = UIColor.whiteColor() 
       } 

       return rowCell 
      } 
     } 
    } 

    // MARK - UICollectionViedDelegate Methods 

    func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) 
    { 
     println(indexPath.section, indexPath.row) 
    } 

    // MARK - Private Methods 

    func getMaxLengthOfTextFromArrayOfData() -> Int 
    { 
     var maxLength = 0 

     for item in self.arrayOfData 
     { 
      if(maxLength < count(item)) 
      { 
       maxLength = count(item) 
      } 
     } 
     println("MaxLength is \(maxLength)") 
     return maxLength 
    } 



} 

UICollectionViewLayout子類

class CustomCollectionViewLayout: UICollectionViewLayout 
{ 
    // The following code is only executed the first time we prepare the layout 
    var numberOfColumns = 0 
    var itemAttributes : NSMutableArray! 
    var itemsSize  : NSMutableArray! 
    var contentSize  : CGSize! 
    var dataForItems : NSMutableArray! 



    override func prepareLayout() 
    { 

     println("prepareLayout") 
     if self.collectionView?.numberOfSections() == 0 
     { 
      return 
     } 

     var tempVar = self.collectionView?.numberOfItemsInSection(0) 
     numberOfColumns = tempVar! 


     // Creating layout attributes of each item by looping though the numberOfItems 

     if (self.itemAttributes != nil && self.itemAttributes.count > 0) 
     { 
      for section in 0..<self.collectionView!.numberOfSections() 
      { 
       var numberOfItems : Int = self.collectionView!.numberOfItemsInSection(section) 

       for index in 0..<numberOfItems 
       { 
        if section != 0 && index != 0 
        { 
         continue 
        } 

        var attributes : UICollectionViewLayoutAttributes = self.layoutAttributesForItemAtIndexPath(NSIndexPath(forItem: index, inSection: section)) 

       } 
      } 
      return 
     } 

     // Calculating the item Size 
     if (self.itemsSize == nil || self.itemsSize.count != numberOfColumns) 
     { 
      self.calculateItemsSize() 
     } 

     var column = 0 

     var xOffset : CGFloat = 0 
     var yOffset : CGFloat = 0 

     var contentWidth : CGFloat = 0 
     var contentHeight : CGFloat = 0 

     // We loop through all items 
     for section in 0..<self.collectionView!.numberOfSections() 
     { 
      var sectionAttributes = NSMutableArray() 

      for index in 0..<numberOfColumns 
      { 
       println("ItemSize - \(self.itemsSize)") 
       var itemSize = self.itemsSize[index].CGSizeValue() 
       var indexPath = NSIndexPath(forItem: index, inSection: section) 
       var attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath) 
       attributes.frame = CGRectIntegral(CGRectMake(xOffset, yOffset, itemSize.width, itemSize.height)) 

       // setting the zIndex of attributes 
       if section == 0 && index == 0 
       { 
        attributes.zIndex = 1024; 
       } 
       else if section == 0 || index == 0 
       { 
        attributes.zIndex = 1023 
       } 

       if section == 0 
       { 
        var frame = attributes.frame 
        frame.origin.y = self.collectionView!.contentOffset.y 
        attributes.frame = frame 
       } 
       if index == 0 
       { 
        var frame = attributes.frame 
        frame.origin.x = self.collectionView!.contentOffset.x 
        attributes.frame = frame 
       } 

       sectionAttributes.addObject(attributes) 

       xOffset += itemSize.width 
       column++ 

       if column == numberOfColumns 
       { 
        if xOffset > contentWidth 
        { 
         contentWidth = xOffset 
        } 

        column = 0 
        xOffset = 0 
        yOffset += itemSize.height 
       } 
      } 
      if (self.itemAttributes == nil) 
      { 
       self.itemAttributes = NSMutableArray(capacity: self.collectionView!.numberOfSections()) 
      } 
      self.itemAttributes .addObject(sectionAttributes) 
     } 

     var attributes : UICollectionViewLayoutAttributes = self.itemAttributes.lastObject?.lastObject as! UICollectionViewLayoutAttributes 
     contentHeight = attributes.frame.origin.y + attributes.frame.size.height 

     self.contentSize = CGSizeMake(contentWidth, contentHeight) 
    } 

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

    override func layoutAttributesForItemAtIndexPath(indexPath: NSIndexPath) -> UICollectionViewLayoutAttributes! 
    { 
     println("layoutAttributesForItemAtIndexPath") 
     return self.itemAttributes[indexPath.section][indexPath.row] as! UICollectionViewLayoutAttributes 
    } 

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [AnyObject]? 
    { 
     println("layoutAttributesForElementsInRect") 
     var attributes : NSMutableArray = NSMutableArray() 

     for section in self.itemAttributes 
     { 
      attributes.addObjectsFromArray(
       section.filteredArrayUsingPredicate(
        NSPredicate(block: { (evaluatedObject, bindings) -> Bool in 

         return CGRectIntersectsRect(rect, evaluatedObject.frame) 
        }) 
       ) 
      ) 
     } 
     return attributes as [AnyObject] 
    } 

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

    // MARK : Private Methods 

    func sizeForItemWithColumnIndex(columnIndex: Int) -> CGSize 
    { 
     println("sizeForItemWithColumnIndex") 
     var text : String = "" 
     switch (columnIndex) 
     { 

     case 0: 
      text = "Col 0" 
     case 1: 
      text = "Col 1" 
     case 2: 
      text = "Col 2" 
     case 3: 
      text = "Col 3" 
     case 4: 
      text = "Col 4" 
     case 5: 
      text = "Col 5" 
     case 6: 
      text = "Col 6" 
     default: 
      text = "Col 7" 

    // HOW DO I GET THE MAX SIZE OF COLUMN CELLs HERE, SO THAT I CAN FIX THE WIDTH OF THE ENTIRE COLUMN?  
     } 

     var size : CGSize = (text as NSString).sizeWithAttributes([NSFontAttributeName: UIFont.systemFontOfSize(17.0)]) 
     let width : CGFloat = size.width + 25 

     println("ItemSize - \(self.itemsSize)") 
     return CGSizeMake(width, 40) 
    } 

    func calculateItemsSize() 
    { 
     println("calculateItemsSize") 
     self.itemsSize = NSMutableArray(capacity: numberOfColumns) 

     // Storing the calculated sizes in itemsSize array in order to do the calculations only once per column. 
     for index in 0..<numberOfColumns 
     { 
      self.itemsSize.addObject(NSValue(CGSize: self.sizeForItemWithColumnIndex(index))) 

     } 
    } 


} 

我的問題 - 如何設置根據的UIlabel裏面的動態大小UICollectionViewCell(ColumnCell)的大小?

回答

2

您需要跟蹤每個網格列的寬度。當標籤動態變化並變得大於當前寬度時,請致電invalidateLayout,以便列中的單元格可以調整它們自己的大小。

+0

嘿@PetahChristian,謝謝你的回覆。但是你能否提供一些我可以將其與我的代碼聯繫起來的例子? – Vineet

+0

任何人都可以請告訴我如何獲得UICollectionViewCell中的UICollectionViewLayout類中的UILabel? – Vineet

相關問題