动态CollectionViewCell在TableViewCell Swift中

时间:2017-10-13 07:21:24

标签: ios swift uitableview uicollectionview row-height

问题:

如何根据UITableViewCell制作UICollectionViewCell高度动态?

查看层次结构:

  

的UIViewController

     
    

的UITableView

         
      

的UITableViewCell

             
        

UICollectionView

                 
          

UICollectionViewCell1

                     
            

标签1

          
                     

UICollectionViewCell2

                     
            

标签2

          
                     

UICollectionViewCell3

                     
            

标签3

          
                     

[等等]

        
      
    
  

说明:

此处Label1Label2label 3具有动态高度,numberOfRows中的UICollectionView也是动态的。根据{{​​1}},我需要UITableViewCell的高度。

2 个答案:

答案 0 :(得分:1)

UICollectionViewCell

中查看层次结构

enter image description here

步骤:

  1. 绑定代理和数据源

    • 使用UIViewController绑定UItableView委托和数据源。

    • 使用UIViewController UICollectionView UItableViewCell绑定TblCell委托和数据源。

  2. UIViewController

    class CollectionVC: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
    :
    :
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableViewAutomaticDimension // For tableCell Dynamic Height
    }
    
    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return 200 // For tableCell Estimated Height
    }
    // Above two delegates must be necessary or you can use property for same.
    
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1 // returning 1, as per current single cell
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TblCell") as! TblCell
    
        return cell
    }
    }
    
  3. TblCell

    class TblCell: UITableViewCell , UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout{
    
    @IBOutlet var colViewObj: UICollectionView!
    
    // Array for Label
    var arrData = ["Hello", "How re you?", "rock the world", "Nice to meet you.", "Hey! It is awsome."]
    
    
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    
        self.colViewObj.isScrollEnabled = false
    }
    
    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    
        // Configure the view for the selected state
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    
         // Get width of Label As per String characters.
        let aWidth : CGFloat = arrData[indexPath.row].width(withConstraintedHeight: 40, font: UIFont.systemFont(ofSize: 17.0))
    
        return CGSize(width: aWidth + 40 , height: 40)
    }
    
    // THIS IS THE MOST IMPORTANT METHOD
    //
    // This method tells the auto layout
    // You cannot calculate the collectionView content size in any other place, 
    // because you run into race condition issues.
    
    override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
    
        // If the cell's size has to be exactly the content 
        // Size of the collection View, just return the
        // collectionViewLayout's collectionViewContentSize.
    
        self.colViewObj.frame = CGRect(x: 0, y: 0,
                                       width: targetSize.width, height: 600)
        self.colViewObj.layoutIfNeeded() 
    
        // It Tells what size is required for the CollectionView
        return self.colViewObj.collectionViewLayout.collectionViewContentSize
    
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return arrData.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ColViewCell", for: indexPath) as! ColViewCell
    
        cell.lblTitle.text = arrData[indexPath.item]
    
        cell.lblTitle.layer.borderColor = UIColor.black.cgColor
        cell.lblTitle.layer.borderWidth = 1.0
    
        return cell
    }
    
    }
    
    extension String {
    
    func width(withConstraintedHeight height: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
    
        return ceil(boundingBox.width)
    }
    }
    
  4. 输出:

    • 红色边框:UITableViewCell
    • 黄色边框:UICollectionViewCell
    • 黑色轮廓:标签

      使用UICollectionViewDelegateFlowLayout

    enter image description here

    没有UICollectionViewDelegateFlowLayout

    enter image description here

    参考:

    UICollectionView inside a UITableViewCell -- dynamic height?

    注意:

    TableViewCell高度基于collectionview内容大小,即如果相同的tableCell具有除collectionview之外的任何其他UI组件,或者collectionView的顶部下边距则不会被计算。为此,您可以创建多个单元格,其中一个单元格仅包含collectionview(现在是最佳方法),或者您可以通过计算在systemLayoutSizeFitting中返回实际的tableview单元格高度。

答案 1 :(得分:0)

如何在swift

中给出符合文本的单元格高度
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
    let message = "Swift is a powerful and intuitive programming language for macOS, iOS, watchOS and tvOS. Writing Swift code is interactive and fun, the syntax is concise yet expressive, and Swift includes modern features developers love."


    let font = UIFont.systemFont(ofSize: 12.0)
    let height = heightForLabel(text: message, font: font, width: self.view.bounds.width )

    if height > 40 {
        return height  
    } else {
        return 40.0;
    }
}


func heightForLabel(text:String, font:UIFont, width:CGFloat) -> CGFloat
{
    let label:UILabel = UILabel(frame: CGRect(x:0,y: 0,width:width,height:CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text

    label.sizeToFit()
    return label.frame.height
}