TableViewCell 中的动态 CollectionViewCell Swift
Dynamic CollectionViewCell In TableViewCell Swift
问题:
如何根据 UICollectionViewCell
?
使 UITableViewCell
高度动态化
查看层次结构:
UIViewController
UITableView
UITableViewCell
UICollectionView
UICollectionViewCell1
Label 1
UICollectionViewCell2
Label 2
UICollectionViewCell3
Label 3
[等等]
解释:
这里的Label1
、Label2
、label 3
都是动态高度,UICollectionView
中的numberOfRows
也是动态的。根据 UICollectionViewCell
.
,我需要 UITableViewCell
的高度
在 UIViewController
中查看层次结构
步骤:
- 绑定委托和数据源
将 UITableView
委托和数据源与 UIViewController
绑定。
在此处 TblCell
.
将 UICollectionView
委托和数据源与 UITableViewCell
绑定
在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
}
}
在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
}
问题:
如何根据 UICollectionViewCell
?
UITableViewCell
高度动态化
查看层次结构:
UIViewController
UITableView
UITableViewCell
UICollectionView
UICollectionViewCell1
Label 1
UICollectionViewCell2
Label 2
UICollectionViewCell3
Label 3
[等等]
解释:
这里的Label1
、Label2
、label 3
都是动态高度,UICollectionView
中的numberOfRows
也是动态的。根据 UICollectionViewCell
.
UITableViewCell
的高度
在 UIViewController
中查看层次结构
步骤:
- 绑定委托和数据源
将
UITableView
委托和数据源与UIViewController
绑定。在此处
将TblCell
.UICollectionView
委托和数据源与UITableViewCell
绑定
在
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 } }
在
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
}