0

I have a tags cloud make with UICollectionView. How make each cell width equal string length?

In collection view i have

1)HEADER (collectionHeader = collectionView for tags)

2)CONTENT ( collection view for content)

HEADER = collection view have class TagCell

listing of this class in footer.

screenshot

----- LISTING COLLECTION VIEW CLASS TagCell -----

 class TagCell: UICollectionViewCell, UICollectionViewDelegateFlowLayout, UICollectionViewDelegate, UICollectionViewDataSource {

var resultController:ResultController?

var tagsName = [String]()
var tagsIndex = [String]()



lazy var mainCollectionView : UICollectionView = {
    let layout = UICollectionViewFlowLayout()
    let mc = UICollectionView(frame: .zero, collectionViewLayout: layout)
    mc.translatesAutoresizingMaskIntoConstraints = false
    mc.delegate = self
    mc.dataSource = self
    return mc
}()


override init(frame : CGRect) {
    super.init(frame: frame)
    setupView()
    mainCollectionView.register(Tags.self, forCellWithReuseIdentifier: "cell")
}

func setupView(){
    addSubview(mainCollectionView)
    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":mainCollectionView]))
    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":mainCollectionView]))
}

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return tagsIndex.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! Tags
    cell.backgroundColor = UIColor.red
    cell.headerLabel.text = tagsName[indexPath.item]
    cell.layer.cornerRadius = 5
    return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    return UIEdgeInsets(top: 10, left: 5, bottom: 10, right: 5)
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    return CGSize(width: 70, height: 30)

    required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}
  }

e.g. after trying @NickCatib answer I got following results enter image description here

---- LISTING TAG CLASS (class for cell)

     class Tags : UICollectionViewCell {

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

var headerLabel:UILabel = {
    let label = UILabel()
    label.text = ""
    label.font = UIFont.systemFont(ofSize: 12)
    label.translatesAutoresizingMaskIntoConstraints = false
    return label
}()

func setupView(){
    addSubview(headerLabel)
    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-2-[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":headerLabel]))
    addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[v0]|", options: NSLayoutFormatOptions(), metrics: nil, views: ["v0":headerLabel]))
}


required init?(coder aDecoder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
}

}

maxim rad
  • 67
  • 8

1 Answers1

1

For this issue I created extension:

extension String
{   
    func widthWithConstrainedHeight(_ height: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: CGFloat.greatestFiniteMagnitude, height: height)

        let boundingBox = self.boundingRect(with: constraintRect, options: .usesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)

        return boundingBox.width
    }
}

You can use it like so:

let font = UIFont.systemFont(ofSize: 12)
let size = string.widthWithConstrainedHeight(17, font: font)
return NSSize(width: size + 10, height: 17)

In your particular case:

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    let string = tagsName[indexPath.item]
    let font = UIFont.systemFont(ofSize: 12)
    let size = string.widthWithConstrainedHeight(30, font: font)
    return NSSize(width: size + 10, height: 30)
}

Note: Be sure to use your font and size as well. Have constraints set on your cell for leading and trailing.

Also, I added 10 for the space on the left and right so it does have some margins.

Miknash
  • 7,888
  • 3
  • 34
  • 46