计算 NSString 高度以在 collectionView 单元格中使用

Posted

技术标签:

【中文标题】计算 NSString 高度以在 collectionView 单元格中使用【英文标题】:calculating NSString height to use in collectionView cells 【发布时间】:2017-12-28 16:07:35 【问题描述】:

我正在尝试创建一个带有动态高度单元格的单列(一种 tableview 样式)的 collectionView。每个单元格将包含一个顶视图,其高度为 50 点,并具有单元格的前导、尾随和顶部约束。唯一的另一件事是下面的一些文本,它们将根据其内容具有动态高度。问题是我尝试使用 boundingRect 方法来计算标签的大小,但是如果文本太长,它将被切断(剪裁)并且单元格没有应有的高度。这是我的代码:

extension CustomCollectionViewController: UICollectionViewDelegateFlowLayout
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize 

    let collectionViewWidth = collectionView.bounds.width
    let topViewHeight: CGFloat = 50
    let topAndBottomMargin: CGFloat = 8
    let width = collectionViewWidth - 4 * 2
    let text = answer[indexPath.item]

    let s = NSString(string: "hello")
    let font = UIFont.systemFont(ofSize: 15)
    let height = calculateTextHeight(for: text, font: font, width: width - 100)

    return CGSize(width: width, height: height + topViewHeight + topAndBottomMargin + 16)



func calculateTextHeight(for text: String, font:UIFont, width: CGFloat) -> CGFloat
    let attributes = [NSFontAttributeName: font]
    let estimateHeight = NSString(string: text).boundingRect(with: CGSize(width: width, height: .greatestFiniteMagnitude), options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: attributes, context: nil)
    let string = NSString(string: text)

    //let estimateHeight = string.size(attributes: [NSFontAttributeName: font])
    print(estimateHeight.height)
    return CGFloat(ceil(estimateHeight.height))



第二件事是我仍然不明白 CGSize 中的宽度如何影响整体高度?

我尝试使用 NSString.size 但这根本不起作用。它严重低估了字符串的高度

【问题讨论】:

单元格中的文本在UILabel中? (你设置了最大行数吗?) 我将它设置为 0,这样它就可以拥有尽可能多的东西 宽度对高度的影响非常明显,因为宽度决定了你的文字是一、二、三行还是更多。 【参考方案1】:

LayoutManager 将调用布局委托来获取项目大小(您实现的那个),但它只会执行一次,然后将此大小作为 layoutAttribute (UICollectionViewLayoutAttributes) 保存在缓存中。

所以也许在您的情况下它使用的是旧尺寸(在缓存中)并且您的集合视图已在两者之间调整了大小?

所以要做的一件事是在集合视图绑定更改时正确重置布局缓存(可能在 viewWillAppear 和 willTransition 中?) 在这种情况下,请执行以下操作:

 let context = UICollectionViewFlowLayoutInvalidationContext()
 context.invalidateFlowLayoutAttributes = true
 context.invalidateFlowLayoutDelegateMetrics = true
 self.collectionView.collectionViewLayout.invalidateLayout(with: context)

通过这样做,布局将清除缓存并要求您提供具有最新宽度的项目的正确宽度。如果您将每个项目设置为最大宽度,您将拥有一列

maxWidth = collectionView.bounds.width - layout.sectionInset.left - layout.sectionInset.right

【讨论】:

以上是关于计算 NSString 高度以在 collectionView 单元格中使用的主要内容,如果未能解决你的问题,请参考以下文章

在iOS 7中获取NSString高度[重复]

Swift开发教程--如何计算字符串的宽度和高度

具有可变高度的自定义单元格

NSDictionary:将 NSString 键转换为小写以在其上搜索字符串

计算文本高度

动态计算文字的高度