2 years ago

#22314

test-img

Kishor Pahalwani

How to implement the "tags layout" using UICollectionView iOS Swift?

I am trying to implement the Tags Layout using UICollectionView. It works fine but only at some places the word is not displayed properly (Cropped) (mostly at the end of the UICollectioView frame). I have attached the screenshot as well. enter image description here

I followed this Setup a collectionView with "tag"-like cells and tried to implement the same but it didn't work for me.

class UserProfileTagsFlowLayout: UICollectionViewFlowLayout {
    
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        guard let attributesForElementsInRect = super.layoutAttributesForElements(in: rect) else { return nil }
        guard var newAttributesForElementsInRect = NSArray(array: attributesForElementsInRect, copyItems: true) as? [UICollectionViewLayoutAttributes] else { return nil }
        
        var leftMargin: CGFloat = 0.0;
        
        for attributes in attributesForElementsInRect {
            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.size.width + 8 // Makes the space between cells
            newAttributesForElementsInRect.append(attributes)
        }
        
        return newAttributesForElementsInRect
    }
}

I am using the below array to populate the data :

data = ["Kishor", "iOS", "Developer", "Software Engineer", "ABCD", "Coding", "Xcode", "I am an iOS Developer","JKLMNO" , "Testing Coding", "Development", "XYZ-XYZ-XYZCD", "Enable the Tag Layout", "Layouts Arrangement"]

But if you see in the screenshot, last word of the first line "ABCD", 'D' is cropped and also few of the words are cropped at the end of the frame.

Below is my UICollectionView (Inside the UITableViewCell)

class TagListCell: UITableViewCell {
    
    @IBOutlet weak var tagListCollection: UICollectionView!
    var data: [String] = []
    
    override func awakeFromNib() {
        super.awakeFromNib()
    }
    
    fileprivate func setCollectioView() {
        self.setupCollectionnViewLayout()
        
        self.tagListCollection.register(UINib(nibName: "TagListNameCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "TagListNameCollectionViewCell")
        tagListCollection.delegate = self
        tagListCollection.dataSource = self
        
    }
    
    private func setupCollectionnViewLayout() {
        let layout = UserProfileTagsFlowLayout()
        //layout.estimatedItemSize = CGSize.init(width: 50, height: 50)
        layout.scrollDirection = .vertical
        tagListCollection.collectionViewLayout = layout
    }
    
    // MARK: UIView functions
    override func systemLayoutSizeFitting(_ targetSize: CGSize, withHorizontalFittingPriority horizontalFittingPriority: UILayoutPriority, verticalFittingPriority: UILayoutPriority) -> CGSize {
        
        self.tagListCollection.layoutIfNeeded()
        let size = tagListCollection.collectionViewLayout.collectionViewContentSize
        let newSize = CGSize(width: size.width, height: size.height + 1)
        debugPrint("New Size : \(newSize)")
        return newSize
    }
    
    func setData(data: [String]) {
        self.setCollectioView()
        self.data = data
    }
}

//MARK:- UICollectionView Delegate and DataSource
extension TagListCell: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return data.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        if let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "TagListNameCollectionViewCell", for: indexPath) as? TagListNameCollectionViewCell {
            cell.titleLable.text = data[indexPath.row]
            return cell
        }
        else {
            return UICollectionViewCell()
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let tag = data[indexPath.row]
        let font = UIFont.systemFont(ofSize: 17)//UIFont(name: "Label Test Data", size: 16)!
        let size = tag.size(withAttributes: [NSAttributedString.Key.font: font])
        let dynamicCellWidth = size.width
        return CGSize(width: dynamicCellWidth, height: 50)
    }
    
    // Space between rows
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 5
    }
    
    // Space between cells
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 5
    }
}

I can't figure out how I can adjust the cell sizes without "breaking" rows count.

ios

swift

uicollectionview

tags

uicollectionviewflowlayout

0 Answers

Your Answer

Accepted video resources