自定义 UITableViewCell 的动态高度问题
Posted
技术标签:
【中文标题】自定义 UITableViewCell 的动态高度问题【英文标题】:Dynamic Height Issue for Custom UITableViewCell 【发布时间】:2020-12-16 16:22:26 【问题描述】:我有一个自定义UITableViewCell
,其中包含一个UICollectionView
。
我在其XIB
文件的每一侧都固定了UICollectionView
。
在我的一些单元格中,内容可能会向下移动,但根据我当前的动态高度设置,我只能看到顶部。我正在将图像添加到我的UICollectionView
,所以在一个单元格中可能有 20 个,而另一个可能只有 5 个。现在每一行都有相同的高度,而有些应该不同。
请注意,单元格中的UICollectionView
不会滚动。
这是我在视图控制器中尝试的:
// Here is where I am getting the arr data, which is the folders
// that contains images.
func getDataForSections()
let storageReference = Storage.storage()
let ref = storageReference.reference().child("abc/xyz/")
ref.listAll (result, error) in
if let error = error
// ...
for prefix in result.prefixes
self.arr.append(prefix)
self.myTableView.reloadData()
func numberOfSections(in tableView: UITableView) -> Int
return arr.count
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return 1
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
let data = arr[indexPath.section]
let cell = tableView.dequeueReusableCell(withIdentifier: "collectionCell", for: indexPath) as! collectionCell
cell.getImagesFromData(data: data)
cell.frame = tableView.bounds
cell.layoutIfNeeded()
cell.collectionView.reloadData()
cell.collectionView.heightAnchor.constraint(equalToConstant: cell.collectionView.collectionViewLayout.collectionViewContentSize.height).isActive = true
cell.layoutIfNeeded()
return cell
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat
// How Do I get the Custom size here? Or in heightForRowAt?
return 500.0
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
return UITableView.automaticDimension
/**
@param numberOfCellsInCollectionView the number of cells of your current collectioview
*/
func calculateHeight(numberOfCellsInCollectionView: Int) -> CGFloat
let imageHeight: CGFloat = 40.0
let spaceBetweenRows: CGFloat = 20.0 /*Change as you please based on the space you put between your cells (if any) */
let rows: CGFloat = CGFloat(calculateRows(numberOfCellsInCollectionView: numberOfCellsInCollectionView))
/**
1) (rows*imageHeight) calculate the total space occupied by the pictures
2) (rows+2) assuming you want to put a little space between the top and the bottom of the collectionview i used +2. If you don't want to remove the +2
3) ((rows+2)*spaceBetweenRows) total space occupied by the spaces.
**/
let height = (rows*imageHeight)+((rows+2)*spaceBetweenRows)
return height
//Calculate the rows
func calculateRows(numberOfCellsInCollectionView: Int) -> Int
let result = numberOfCellsInCollectionView/6 //Dividing the number of cells for the cells for row
let rest = numberOfCellsInCollectionView%6 //Calculating the module
if rest == 0
//If the rest is 0 (ie: you divide 18/6), then you get the result of the division (18/6 = 3)
return result
else
//If the rest is > 0 (ie: you divide 17/6), then you get the result of the division + 1 (17/6 = 3+1 = 4) so there's space for the last item
return result+1
这是我在具有集合视图的自定义单元格中尝试的内容:
func getImagesFromData(prefix: String)
let storageReference = Storage.storage()
let ref = storageReference.reference().child("abc/xyz/\(prefix)")
ref.listAll (result, error) in
if let error = error
// ...
self.folderImages.removeAll()
for item in result.items
if !self.folderImages.contains(item)
self.folderImages.append(item)
// Here is where I need to store (or retain) the count
// for each section and then calculate the height or pass
// this data back to the View Controller.
// But with Firebase I am not sure how to return this or
// use a completion.
// reload collection data
self.myCollectionView.reloadData()
extension customCollectionCell: UICollectionViewDataSource, UICollectionViewDelegate
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
return folderImages.count
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "imageCell", for: indexPath) as! imageCell
let theImage = folderImages[indexPath.item]
cell.imageView.sd_setImage(with: theImage, placeholderImage: UIImage(named: "blah")) (image, error, cacheType, ref) in
if error != nil
cell.imageView.image = UIImage(named: "blah")
return cell
另一个例子:
这里不是使用UITableView
和UICollectionViewCell
,而是使用UICollectionView
和UICollectionViewCell
...
我还使用UIViewController
中单元格内的方法的变体来获取计数。
在这个例子中,我可以看到返回之前的值。我只需要知道如何在返回值中获取该值作为高度。
这是我尝试过的:
func collectionView(_ collectionView: UICollectionView,
layout collectionViewLayout: UICollectionViewLayout,
sizeForItemAt indexPath: IndexPath) -> CGSize
let prefix = arr[indexPath.section]
getImageCountFromPrefix(prefix: prefix.name, completion: (count, success) in
if success
self.h = self.calculateHeight(numberOfCellsInCollectionView: count)
// self.h has a value!!! How do I get it in the return?
)
return CGSize(width: collectionView.bounds.size.width, height: self.h)
【问题讨论】:
【参考方案1】:创建一个函数来确定单元格内图片的高度,然后只使用heightForRowAtIndexPath
函数,如下所示:
private func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
/* Here I'll just assume the height of the picture is 30. You'll have to put here your function and return the dimension. */
return 30.0
请注意,您可能希望在返回值中添加一个常量值,以使单元格的外观更加清晰。我一般加70.0
哦,我不知道图像,但是当您处理文本时,您还必须在 cellForRowAt
中调用这些。
cell.textLabel?.sizeToFit()
cell.textLabel?.numberOfLines = 0
这里是如何计算你的收藏视图的高度
/**
@param numberOfCellsInCollectionView the number of cells of your current collectioview
*/
func calculateHeight(numberOfCellsInCollectionView: Int) -> CGFloat
let imageHeight: CGFloat = 40.0
let spaceBetweenRows: CGFloat = 5.0 /*Change as you please based on the space you put between your cells (if any) */
let rows: CGFloat = CGFloat(calculateRows(numberOfCellsInCollectionView: numberOfCellsInCollectionView))
/**
1) (rows*imageHeight) calculate the total space occupied by the pictures
2) (rows+2) assuming you want to put a little space between the top and the bottom of the collectionview i used +2. If you don't want to remove the +2
3) ((rows+2)*spaceBetweenRows) total space occupied by the spaces.
**/
let height = (rows*imageHeight)+((rows+2)*spaceBetweenRows)
return height
//Calculate the rows
func calculateRows(numberOfCellsInCollectionView: Int) -> Int
let result = numberOfCellsInCollectionView/6 //Dividing the number of cells for the cells for row
let rest = numberOfCellsInCollectionView%6 //Calculating the module
if rest == 0
//If the rest is 0 (ie: you divide 18/6), then you get the result of the division (18/6 = 3)
return result
else
//If the rest is > 0 (ie: you divide 17/6), then you get the result of the division + 1 (17/6 = 3+1 = 4) so there's space for the last item
return result+1
【讨论】:
图片为 40x40。 UICollectionView 已设置好,因此将连续出现 6 个。 对,我的错,我忽略了部分问题。但是,您应该计算集合视图的高度并将其返回到 heightForRowAtIndexPath 中。您还应该调用 cell.sizeToFit() 但我不知道 numberOfLines 的等价物。如果您需要更多帮助,请告诉我 关于计算 UICollectionView 高度的最佳方法有什么建议吗?所以现在我得到的值看起来是我需要的,但这是在其他所有内容都加载之后。所以不确定如何正确返回该值。 感谢您对此提供的帮助。所以,虽然这些确实返回了我需要的值,但我仍然不知道应该在哪里调用它们。在我可以将值传递给它之前,我的所有设置都已加载。我正在使用 Firebase。所以我想知道是不是因为这个。我似乎无法找到如何从他们的方法中返回值,并且我可以在任何调整大小的方法中使用它们。 在heightForRowAtIndexPath中调用计算高度,使其成为返回值。如果在加载视图之前无法访问数据,这不是问题。您可以创建辅助变量,您将在加载所需数据后为其赋值。使用这些辅助变量代替您丢失的数据。以上是关于自定义 UITableViewCell 的动态高度问题的主要内容,如果未能解决你的问题,请参考以下文章
IOS:具有自定义 uitableviewcell 的动态高度
根据标签文本长度动态自定义 UITableViewCell 的高度
如何在swift中设置自定义UITableviewcell的动态高度
Swift中基于标签文本长度的动态自定义UITableViewCell的高度