多行UILabel导致额外的填充

时间:2018-09-27 20:28:42

标签: ios swift uilabel uicollectionviewcell cgsize

我有一个具有标签和imageView的collectionView单元格。 imageView是从单元格顶部起的8个点,标签的顶部是imageView底部起的8个点,标签的底部是该单元格的底部起8个点。当标签距离单元格的右边缘-10点时,标签会自动换行。

标签中的文本可以跨越多行。我在collectionView的sizeForItem中使用以下函数来计算标签的高度:

func estimatedLabelHeight(text: String, width: CGFloat, font: UIFont) -> CGFloat {

    let size = CGSize(width: width, height: 1000)

    let options = NSStringDrawingOptions.usesFontLeading.union([.usesLineFragmentOrigin, .usesFontLeading])

    let attributes = [NSAttributedStringKey.font: font]

    let rectangleHeight = String(text).boundingRect(with: size, options: options, attributes: attributes, context: nil).height

    return rectangleHeight
}

该单元格可以正确展开,但是标签上添加了额外的填充,我无法弄清楚如何清除它。

enter image description here

这是正确包装的多行标签尺寸22。我在3D检查器中为其拍照。如您所见,在标签文本上方和下方的顶部和底部都有大量的填充。标签在imageView下的8点间距是正确的,但是额外的填充使其看起来像24点间距。

奇怪的是,即使我将标签的尺寸减小到16,额外的填充仍然存在。

如何删除此填充?

collectionView的sizeForItem,其中调用了labeledLabelHeight函数:

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

    let profileImageViewHeight: CGFloat = 50 // imageView height is set to 50 inside the cell

    let padding: CGFloat = 24 // 8 x 8 x 8 the vertical padding inside the cell between the titleLabel, the imageView, and the cell

    // estimatedLabelHeight is called here
    let titleLabelHeight = estimatedLabelHeight(text: "some very very long text...", width: view.frame.width - 20, font: UIFont.systemFont(ofSize: 22))

    let totalHeightOfCell = titleLabelHeight + profileImageViewHeight + padding

    return CGSize(width: view.frame.width, height: totalHeightOfCell)
}

单元格:

class MyCell: UICollectionViewCell{

    let titleLabel: UILabel = {
        let label = UILabel()
        label.translatesAutoresizingMaskIntoConstraints = false
        label.font = UIFont.systemFont(ofSize: 22)
        label.textColor = UIColor.black
        label.textAlignment = .left
        label.sizeToFit()
        label.numberOfLines = 0
        return label
    }()

    let profileImageView: UIImageView = {
        // created it...
    }

    override init(frame: CGRect) {
        super.init(frame: frame)

        addSubview(profileImageView)
        addSubview(titleLabel)

        profileImageView.topAnchor.constraint(equalTo: self.topAnchor, constant: 8).isActive = true
        profileImageView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
        profileImageView.widthAnchor.constraint(equalToConstant: 50).isActive = true
        profileImageView.heightAnchor.constraint(equalToConstant: 50).isActive = true

        titleLabel.topAnchor.constraint(equalTo: profileImageView.bottomAnchor, constant: 8).isActive = true
        titleLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
        titleLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10).isActive = true
        titleLabel.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -8).isActive = true

        // I tried to set the label's height using the below but the same padding issue occured
        // let titleLabelHeight = estimatedLabelHeight(text: titleLabel.text!, width: self.frame.width - 20, font: UIFont.systemFont(ofSize: 22))
        // titleLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: titleLabelHeight).isActive = true
    }
}

1 个答案:

答案 0 :(得分:0)

问题是由于我自己的粗心。 @CSmith提示了如何测量sizeForItem的高度以及单元格的框架,这是使我缩小范围的原因。

在collectionView单元格内的项目中,我将imageView的底部锚点设置为8而不是-8,在collectionView的sizeForItem内,我的总高度为24。之所以发生冲突,是因为因为我在单元格内有8在collectionView中应该是16,并且不匹配以某种方式扩展了标签。一旦我更正并更改了imageView的底部锚点-8,一切都匹配了,标签的填充问题就解决了。