Ios UITableViewCell动态高度内的非滚动UICollectionView
我在Ios UITableViewCell动态高度内的非滚动UICollectionView,ios,swift,uitableview,uicollectionview,autolayout,Ios,Swift,Uitableview,Uicollectionview,Autolayout,我在UITableViewCell中添加了UICollectionView,为此我创建了XIB文件。检查以下图像: 您可以在上图中看到所有视图的层次结构和约束 注意:我已禁用垂直和水平收集视图 滚动,因为我想动态增加UITableViewCell高度。所以我采用了集合视图的高度约束的出水口,并根据集合视图中可用的项目以编程方式对其进行更改 集合视图的项目大小如果固定,则宽度与集合视图成比例,高度为30 我已经使用以下代码在我的表视图中注册了这个xib self.tblSubCategory.r
UITableViewCell
中添加了UICollectionView
,为此我创建了XIB
文件。检查以下图像:
您可以在上图中看到所有视图的层次结构和约束
注意:我已禁用垂直和水平收集视图
滚动,因为我想动态增加UITableViewCell
高度。所以我采用了集合视图的高度约束的出水口,并根据集合视图中可用的项目以编程方式对其进行更改
集合视图的项目大小如果固定,则宽度与集合视图成比例,高度为30
我已经使用以下代码在我的表视图中注册了这个xib
self.tblSubCategory.register(SubCategoryTVC.Nib(), forCellReuseIdentifier: "SubCategoryTVC")
这是我的子类别tvc
代码:
class SubCategoryTVC: UITableViewCell {
@IBOutlet weak var categoryView : UIView!
@IBOutlet weak var categoryImageView : UIView!
@IBOutlet weak var imgCategory : UIImageView!
@IBOutlet weak var lblCategoryName : UILabel!
@IBOutlet weak var cvSubcategory : UICollectionView!
// MARK: Constrains's Outlet
@IBOutlet weak var const_cvSubcategory_height : NSLayoutConstraint!
class func Nib() -> UINib {
return UINib(nibName: "SubCategoryTVC", bundle: nil)
}
func setCollectionView(dataSourceDelegate: UICollectionViewDataSource & UICollectionViewDelegate, forRow row: Int) {
self.cvSubcategory.delegate = dataSourceDelegate
self.cvSubcategory.dataSource = dataSourceDelegate
self.cvSubcategory.tag = row
self.cvSubcategory.reloadData()
}
override func awakeFromNib() {
super.awakeFromNib()
}
}
UITableViewDataSource:
extension SignupSecondStepVC: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
//------------------------------------------------------------------------------
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SubCategoryTVC", for: indexPath) as! SubCategoryTVC
cell.lblCategoryName.text = "Category \(indexPath.row)"
cell.cvSubcategory.register(SubCategoryCVC.Nib(), forCellWithReuseIdentifier: "SubCategoryCVC")
return cell
}
}
extension SignupSecondStepVC: UITableViewDelegate {
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let subCategoryCell = cell as? SubCategoryTVC else { return }
// This line of code set dataSource and delegate to `SignupSecondStepVC` instead of `SubCategoryTVC`
subCategoryCell.setCollectionView(dataSourceDelegate: self, forRow: indexPath.row)
subCategoryCell.cvSubcategory.setNeedsLayout()
// This will change height of collection view based on item available.
subCategoryCell.const_cvSubcategory_height.constant = 30 * 5
subCategoryCell.cvSubcategory.setNeedsLayout()
subCategoryCell.contentView.layoutIfNeeded()
}
//------------------------------------------------------------------------------
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
//------------------------------------------------------------------------------
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
extension SignupSecondStepVC: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
//------------------------------------------------------------------------------
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SubCategoryCVC", for: indexPath) as! SubCategoryCVC
cell.btnSelection.setCornerRadius(radius: cell.btnSelection.frame.size.height / 2)
cell.lblSubCategoryName.text = "SubCategory \(indexPath.row)"
return cell
}
}
extension SignupSecondStepVC: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.frame.size.width
return CGSize(width: width, height: 30)
}
}
UITableViewDelegate:
extension SignupSecondStepVC: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
//------------------------------------------------------------------------------
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SubCategoryTVC", for: indexPath) as! SubCategoryTVC
cell.lblCategoryName.text = "Category \(indexPath.row)"
cell.cvSubcategory.register(SubCategoryCVC.Nib(), forCellWithReuseIdentifier: "SubCategoryCVC")
return cell
}
}
extension SignupSecondStepVC: UITableViewDelegate {
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let subCategoryCell = cell as? SubCategoryTVC else { return }
// This line of code set dataSource and delegate to `SignupSecondStepVC` instead of `SubCategoryTVC`
subCategoryCell.setCollectionView(dataSourceDelegate: self, forRow: indexPath.row)
subCategoryCell.cvSubcategory.setNeedsLayout()
// This will change height of collection view based on item available.
subCategoryCell.const_cvSubcategory_height.constant = 30 * 5
subCategoryCell.cvSubcategory.setNeedsLayout()
subCategoryCell.contentView.layoutIfNeeded()
}
//------------------------------------------------------------------------------
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
//------------------------------------------------------------------------------
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
extension SignupSecondStepVC: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
//------------------------------------------------------------------------------
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SubCategoryCVC", for: indexPath) as! SubCategoryCVC
cell.btnSelection.setCornerRadius(radius: cell.btnSelection.frame.size.height / 2)
cell.lblSubCategoryName.text = "SubCategory \(indexPath.row)"
return cell
}
}
extension SignupSecondStepVC: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.frame.size.width
return CGSize(width: width, height: 30)
}
}
以上代码用于UITableView
,请参见UICollectionView
UICollectionViewDataSource:
extension SignupSecondStepVC: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
//------------------------------------------------------------------------------
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SubCategoryTVC", for: indexPath) as! SubCategoryTVC
cell.lblCategoryName.text = "Category \(indexPath.row)"
cell.cvSubcategory.register(SubCategoryCVC.Nib(), forCellWithReuseIdentifier: "SubCategoryCVC")
return cell
}
}
extension SignupSecondStepVC: UITableViewDelegate {
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let subCategoryCell = cell as? SubCategoryTVC else { return }
// This line of code set dataSource and delegate to `SignupSecondStepVC` instead of `SubCategoryTVC`
subCategoryCell.setCollectionView(dataSourceDelegate: self, forRow: indexPath.row)
subCategoryCell.cvSubcategory.setNeedsLayout()
// This will change height of collection view based on item available.
subCategoryCell.const_cvSubcategory_height.constant = 30 * 5
subCategoryCell.cvSubcategory.setNeedsLayout()
subCategoryCell.contentView.layoutIfNeeded()
}
//------------------------------------------------------------------------------
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
//------------------------------------------------------------------------------
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
extension SignupSecondStepVC: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
//------------------------------------------------------------------------------
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SubCategoryCVC", for: indexPath) as! SubCategoryCVC
cell.btnSelection.setCornerRadius(radius: cell.btnSelection.frame.size.height / 2)
cell.lblSubCategoryName.text = "SubCategory \(indexPath.row)"
return cell
}
}
extension SignupSecondStepVC: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.frame.size.width
return CGSize(width: width, height: 30)
}
}
UICollectionViewDelegateFlowLayout:
extension SignupSecondStepVC: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
//------------------------------------------------------------------------------
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SubCategoryTVC", for: indexPath) as! SubCategoryTVC
cell.lblCategoryName.text = "Category \(indexPath.row)"
cell.cvSubcategory.register(SubCategoryCVC.Nib(), forCellWithReuseIdentifier: "SubCategoryCVC")
return cell
}
}
extension SignupSecondStepVC: UITableViewDelegate {
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let subCategoryCell = cell as? SubCategoryTVC else { return }
// This line of code set dataSource and delegate to `SignupSecondStepVC` instead of `SubCategoryTVC`
subCategoryCell.setCollectionView(dataSourceDelegate: self, forRow: indexPath.row)
subCategoryCell.cvSubcategory.setNeedsLayout()
// This will change height of collection view based on item available.
subCategoryCell.const_cvSubcategory_height.constant = 30 * 5
subCategoryCell.cvSubcategory.setNeedsLayout()
subCategoryCell.contentView.layoutIfNeeded()
}
//------------------------------------------------------------------------------
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
//------------------------------------------------------------------------------
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
extension SignupSecondStepVC: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
//------------------------------------------------------------------------------
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SubCategoryCVC", for: indexPath) as! SubCategoryCVC
cell.btnSelection.setCornerRadius(radius: cell.btnSelection.frame.size.height / 2)
cell.lblSubCategoryName.text = "SubCategory \(indexPath.row)"
return cell
}
}
extension SignupSecondStepVC: UICollectionViewDelegateFlowLayout {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = collectionView.frame.size.width
return CGSize(width: width, height: 30)
}
}
在完成所有这些事情之后,我对单元格加载和UI产生了问题。当我第一次运行应用程序并加载数据时,UI出现问题,数据加载不正确。请看下面的视频,以便您了解我的实际问题
请帮助我解决此问题。您需要将collectionView委托/数据源与TableViewCell绑定,并需要在TableViewCell中使用以下函数。确保关闭CollectionView滚动
override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
self.layoutIfNeeded()
let contentSize = self.cvSubcategory.collectionViewLayout.collectionViewContentSize
if self.cvSubcategory.numberOfItems(inSection: 0) < 4 {
return CGSize(width: contentSize.width, height: 120) // Static height if colview is not fitted properly.
}
return CGSize(width: contentSize.width, height: contentSize.height + 20) // 20 is the margin of the collectinview with top and bottom
}
覆盖func systemLayoutSizeFitting(uuTargetSize:CGSize,带水平装配优先级水平装配优先级:UILayoutPriority,垂直装配优先级:UILayoutPriority)->CGSize{
self.layoutifneed()
让contentSize=self.cvSubcategory.collectionViewLayout.collectionViewContentSize
如果self.cvSubcategory.numberOfItems(第0节)<4{
返回CGSize(width:contentSize.width,height:120)//如果colview未正确安装,则返回静态高度。
}
返回CGSize(width:contentSize.width,height:contentSize.height+20)//20是CollectionView的页边距,包括顶部和底部
}
您的项目示例解决方案:
为了将来的目的,你可以从这篇文章中引用:返回
estimatedHeightForRowAt
中的任何值,比如40、50。@DahiyafBoy,我已经尝试过estimatedHeightForRowAt
,但它不起作用。在重新加载调用self.layoutNeedd()
@DahiyafBoy,我已经尝试过上面的方法,但它不起作用。请共享具有相同条件和问题的示例项目。我会帮你查的。