0
votes

I wish to create a uicollectionview which looks like this.

Collectionview

The height of the cells will be constant, but the width should automatically change dependant on the length of the label text.

FlowLayout:

        func prepareFlowLayout() -> UICollectionViewFlowLayout{
    let flowLayout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
    flowLayout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
    flowLayout.minimumInteritemSpacing = 3
    flowLayout.minimumLineSpacing = 3
    return flowLayout
}

Label:

let nameLabel: UILabel = {
    let label = UILabel()
    label.translatesAutoresizingMaskIntoConstraints = false
    //label.backgroundColor = .black

    return label
}()

Autolayout inside cell:

 backgroundColor = .green
    let conView = contentView
    layer.cornerRadius = 5
    clipsToBounds = true
    conView.addSubview(nameLabel)
    NSLayoutConstraint.activate([
        nameLabel.centerXAnchor.constraint(equalTo: conView.centerXAnchor, constant: 0),
        nameLabel.centerYAnchor.constraint(equalTo: conView.centerYAnchor, constant: 0),
        nameLabel.heightAnchor.constraint(equalTo: conView.heightAnchor, multiplier: 0.8),
        nameLabel.widthAnchor.constraint(equalTo: conView.widthAnchor, multiplier: 0.8)
    ])

Result as of now: enter image description here

Could anyone send me in the right direction for finding a way which would achieve this?

1
In this case your cells are sized correctly for their content, but you need them to take up the extra space (divided evenly amongst the cells I assume). You cannot do this from with in a single cell; you will need to subclass UICollectionViewLayout and calculate the attributes there, since it can consider all of the cells on a row together. - Josh Homann

1 Answers

0
votes

What I did is use the sizeForItemAt function for check the correct size of the view, depending to the text.

// MARK: - UICollectionViewDelegateFlowLayout
extension <#myCollectionVC#>: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let height: CGFloat = <#myHeight#>

        //Calculate size for current view
        let stringName: NSString = <#myObjects#>[indexPath.row] as NSString
        let width = stringName.size(attributes: [NSFontAttributeName: UIFont.systemFont(ofSize: 14)]).width
        let padding: CGFloat = <#yourTotalPaddingSize#>
        return CGSize(width: width + padding, height: height)
    }
}

After that, you'll probably want to align left al your views, in that case, you need to create your own UICollectionViewFlowLayout, and assigned to your collectionView (select the Collection View Flow Layout in your storyboard, inside your collection view, and change the class name to MyCustomviewLayout) :

class <#MyCustomViewLayout#>: UICollectionViewFlowLayout {
    let spacing = CGFloat(<#spacing#>) // spacing between views

    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        guard let oldAttributes = super.layoutAttributesForElements(in: rect) else {
            return super.layoutAttributesForElements(in: rect)
        }

        var newAttributes = [UICollectionViewLayoutAttributes]()
        var leftMargin = self.sectionInset.left
        for attributes in oldAttributes {
            if (attributes.frame.origin.x == self.sectionInset.left) {
                leftMargin = self.sectionInset.left
            } else {
                var newLeftAlignedFrame = attributes.frame
                newLeftAlignedFrame.origin.x = leftMargin
                attributes.frame = newLeftAlignedFrame
            }

            leftMargin += attributes.frame.width + spacing
            newAttributes.append(attributes)
        }
        return newAttributes
    }
}