在调整标签文本以自动捕获collectionView单元格时,我在sizeForItem中使用以下功能:
func estimatedLabelHeight(text: String, width: CGFloat, font: UIFont) -> CGFloat {
let size = CGSize(width: width, height: 1000)
let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
let attributes = [NSAttributedStringKey.font: font]
let rectangleHeight = String(text).boundingRect(with: size, options: options, attributes: attributes, context: nil).height
return rectangleHeight
}
该功能正常运行,并且我的单元格相应扩展。
尽管发生了什么,但是pricesLabel的某些文本中有多个换行符,这些换行符被馈送到函数中。换行符太“紧”,所以我跟随this answer when creating my label扩大了换行符之间的间隔。
let attributedString = NSMutableAttributedString(string: pricesText)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 7 // if I set this at 2 I have no problems
attributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, attributedString.length))
问题是单元格中来自pricesLabel的文本向下扩展到了很远。使用paragraphStyle.lineSpacing = 7
会创建我想要的空间,但会引起问题。如果我将其设置为paragraphStyle.lineSpacing = 2
没问题,但是间距要紧。
您可以在图片中看到单元格的大小,但换行符介于$ 8.00和$ 12.00之间,使文本扩展到很远,而computeTotalLabel中的$ 20.00文本变得模糊了。
我在sizeToFit()
中叫layoutSubViews()
,但没什么区别:
override func layoutSubviews() {
super.layoutSubviews()
pricesLabel.sizeToFit()
computedTotalLabel.sizeToFit()
}
如何根据行间断本身的大小调整pricesLabel文本
class MyCell: UICollectionViewCell {
let pricesLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textAlignment = .right
label.sizeToFit()
label.font = UIFont.systemFont(ofSize: 15.5)
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.5
label.numberOfLines = 0
label.sizeToFit()
return label
}()
let computedTotalLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textAlignment = .right
label.textColor = .black
label.sizeToFit()
label.font = UIFont.boldSystemFont(ofSize: 15.5)
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.5
label.numberOfLines = 1
label.sizeToFit()
return label
}()
let staticTotalLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.text = "Total"
label.textAlignment = .left
label.textColor = .black
label.font = UIFont.boldSystemFont(ofSize: 15.5)
label.adjustsFontSizeToFitWidth = true
label.minimumScaleFactor = 0.5
label.numberOfLines = 1
label.sizeToFit()
return label
}()
let separatorLine: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
view.backgroundColor = .lightGray
return view
}()
override func layoutSubviews() {
super.layoutSubviews()
pricesLabel.sizeToFit()
computedTotalLabel.sizeToFit()
}
var myObject: MyObject? {
didSet {
// text is "$8.00\n$12.00\n"
let pricesText = myObject?.myText ?? "error"
let attributedString = NSMutableAttributedString(string: pricesText, attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 15.5)])
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 7
attributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, attributedString.length))
pricesLabel.attributedText = attributedString
computedTotalLabel.text = functionThatTalliesUpAllThePrices(pricesText)
configureAnchors()
}
}
func configureAnchors() {
addSubview(pricesLabel)
addSubview(totalLabel)
addSubview(staticTotalLabel) // this is the label on the left side of the pic that says Total:
addSubview(separatorLine)
pricesLabel.topAnchor.constraint(equalTo: self.topAnchor, constant: 12).isActive = true
pricesLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10).isActive = true
staticTotalLabel.lastBaselineAnchor.constraint(equalTo: totalLabel.lastBaselineAnchor).isActive = true
staticTotalLabel.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
staticTotalLabel.rightAnchor.constraint(equalTo: totalLabel.leftAnchor, constant: -10).isActive = true
computedTotalLabel.topAnchor.constraint(equalTo: pricesLabel.bottomAnchor, constant: 0).isActive = true
computedTotalLabel.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10).isActive = true
separatorLine.topAnchor.constraint(equalTo: computedTotalLabel.bottomAnchor, constant: 12).isActive = true
separatorLine.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 10).isActive = true
separatorLine.rightAnchor.constraint(equalTo: self.rightAnchor, constant: -10).isActive = true
separatorLine.bottomAnchor.constraint(equalTo: self.bottomAnchor).isActive = true
separatorLine.heightAnchor.constraint(equalToConstant: 1).isActive = true
}
}
这是collectionView单元内的sizeForItem。不知道这是否可以解决问题,所以我还是添加了它
class MyClass: UIViewController {
let tableData = [MyObect]()
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let myObect = tableData[indexPath.item]
// text is "$8.00\n$12.00\n"
let pricesText = myObject?.myText ?? "error"
let width = collectionView.frame.width
let pricesLabelHeight = estimatedLabelHeight(text: pricesText, width: width, font: UIFont.systemFont(ofSize: 15.5))
let total = functionThatTalliesUpAllThePrices(pricesText)
let totalLabelHeight = estimatedLabelHeight(text: functionThatAddsUp, width: width, font: UIFont.boldSystemFont(ofSize: 15.5))
// the 12 + 0 + 12 + 1 are the constant sizes I use inside the cell's configureAnchors functions
let cellHeight = 12 + pricesLabelHeight + 0 + totalLabelHeight + 12 + 1
return CGSize(width: width, height: ceil(cellHeight))
}
}
答案 0 :(得分:0)
1st。我必须将相同的estimatedLabelHeight(text: String, width: CGFloat, font: UIFont)
放在collectionView单元格本身中。
第二。在其底部的configureAnchors函数内部,我分别调用pricesLabel.sizeToFit()
和pricesLabel.layoutSubviews()
,然后从步骤1中调用上述函数,以从其文本中获取pricesLabel的高度。
3rd。我将pricesLabel.heightAnchor.constraint(equalToConstant:)
设置为步骤2返回的高度。
class MyCell: UICollectionViewCell {
// step 1. place this function inside the collectionView cell
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
}
func configureAnchors() {
// all the other anchors are here
pricesLabel.sizeToFit()
computedTotalLabel.sizeToFit()
computedTotalLabel.layoutIfNeeded()
pricesLabel.layoutIfNeeded()
let pricesLabelText = pricesLabel.text ?? "error"
let width = self.frame.width
// step 2.
let pricesLabelHeight = estimatedLabelHeight(text: pricesLabelText, width: width, font: UIFont.systemFont(ofSize: 15.5))
// step 3.
pricesLabel.heightAnchor.constraint(equalToConstant: pricesLabelHeight).isActive = true
}
}