HorizontalCollectionView Content width and spacing

前端 未结 2 965
野趣味
野趣味 2021-01-24 20:47

How can I make my horizontal collection view labels width to wrap the content width of the label and make them have equal spacing between each of them? Currently I have

2条回答
  •  别那么骄傲
    2021-01-24 21:12

    Calculate the width of the label text first with the font associated with the text.

    extension String {
        func size(with font: UIFont) -> CGSize {
            let fontAttribute = [NSAttributedString.Key.font: font]
            let size = self.size(withAttributes: fontAttribute)
            return size
        }
    }
    

    Return the calculated width along with collectionView height in collectionView(_, collectionViewLayout:_, sizeForItemAt).

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    
        let newWidth = titles[indexPath.row].size(with: labelFont!).width + 10 //Added 10 to make the label visibility very clear
        return CGSize(width: newWidth, height: collectionView.bounds.height)
    }
    

    Entire source code:

    class ViewController: UIViewController {
    
        @IBOutlet weak var collection: UICollectionView!
    
        let labelFont = UIFont(name: "Helvetica Neue", size: 18)
        let titles = ["Hi", "Hello", "HorizontalCollectionView", "VerticalCollectionView"]
    
        override func viewDidLoad() {
    
            super.viewDidLoad()
            collection.backgroundColor = UIColor(red: 68/255, green: 143/255, blue: 1, alpha: 1)
            collection.register(UINib.init(nibName: "CustomCollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CustomCollectionViewCell")
        }
    }
    
    extension ViewController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    
            return titles.count
        }
    
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
    
            return UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
        }
    
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
    
            return 0
        }
    
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
    
            return 10 // Adjust the inter item space based on the requirement.
        }
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    
        let newWidth = titles[indexPath.row].size(with: labelFont!).width + 10 //Added 10 to make the label visibility very clear
        return CGSize(width: newWidth, height: collectionView.bounds.height)
    }
    
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCollectionViewCell", for: indexPath) as! CustomCollectionViewCell
            cell.titleLabel.text = titles[indexPath.row]
            cell.titleLabel.font = labelFont!
            return cell
        }
    }
    
    extension String {
        func size(with font: UIFont) -> CGSize {
            let fontAttribute = [NSAttributedString.Key.font: font]
            let size = self.size(withAttributes: fontAttribute)
            return size
        }
    }
    

    Another Solution:

    ViewController.swift

    class ViewController: UIViewController,UICollectionViewDelegate,UICollectionViewDataSource {
    
        @IBOutlet weak var collView: UICollectionView!
    
    
        var tasksArray = ["To Do", "SHOPPING","WORK"]
        var selectedIndex = Int()
    
        override func viewDidLoad() {
            super.viewDidLoad()
            collView.register(UINib.init(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "Cell")
            let layout = collView?.collectionViewLayout as! UICollectionViewFlowLayout
            layout.itemSize = UICollectionViewFlowLayout.automaticSize
            layout.estimatedItemSize = CGSize(width: 170, height: 50)
            // Do any additional setup after loading the view, typically from a nib.
        }
        func numberOfSections(in collectionView: UICollectionView) -> Int {
            return 1
        }
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return tasksArray.count
        }
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionViewCell
            cell.lblName.text = tasksArray[indexPath.row]
            if selectedIndex == indexPath.row
            {
                cell.backgroundColor = UIColor.lightGray
            }
            else
            {
                cell.backgroundColor = UIColor.white
            }
            return cell
        }
        func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
            selectedIndex = indexPath.row
            self.collView.reloadData()
        }
    }
    

    Cell.swift

    class CollectionViewCell: UICollectionViewCell {
    
        @IBOutlet weak var lblName: UILabel!
    
        override func awakeFromNib() {
            super.awakeFromNib()
            // Initialization code
            layer.borderWidth = 1
            layer.cornerRadius = bounds.height / 2
        }
    
        override func preferredLayoutAttributesFitting(_ layoutAttributes: UICollectionViewLayoutAttributes) -> UICollectionViewLayoutAttributes {
            setNeedsLayout()
            layoutIfNeeded()
            let size = contentView.systemLayoutSizeFitting(layoutAttributes.size)
            var frame = layoutAttributes.frame
            frame.size.width = ceil(size.width)
            layoutAttributes.frame = frame
            return layoutAttributes
        }
    }
    

提交回复
热议问题