TableViewCell 中的动态 CollectionViewCell Swift

Dynamic CollectionViewCell In TableViewCell Swift

问题:

如何根据 UICollectionViewCell?

使 UITableViewCell 高度动态化

查看层次结构:

UIViewController

UITableView

UITableViewCell

UICollectionView

UICollectionViewCell1

Label 1

UICollectionViewCell2

Label 2

UICollectionViewCell3

Label 3

[等等]

解释:

这里的Label1Label2label 3都是动态高度,UICollectionView中的numberOfRows也是动态的。根据 UICollectionViewCell.

,我需要 UITableViewCell 的高度

UIViewController

中查看层次结构

步骤:

  1. 绑定委托和数据源
  • UITableView 委托和数据源与 UIViewController 绑定。

  • 在此处 TblCell.

    UICollectionView 委托和数据源与 UITableViewCell 绑定
  1. 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
     }
     }
    
  2. 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)
     }
     }
    

输出:

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

与 UICollectionViewDelegateFlowLayout

没有UICollectionViewDelegateFlowLayout

参考:

UICollectionView inside a UITableViewCell -- dynamic height?

注:

TableViewCell 高度基于 collectionview 内容大小,即如果相同的 tableCell 有除 collectionview 之外的任何其他 UI 组件或有顶部底部collectionView 的保证金则不会被计算。为此,您可以创建多个单元格,其中一个单元格仅包含 collectionview(目前最佳方法),或者您可以通过计算 return systemLayoutSizeFitting 中的实际 tableViewCell 高度。

如何根据 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
}