HorizontalCollectionView Content width and spacing

前端 未结 2 964
野趣味
野趣味 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:09

    You have to manually calculate the width of each cell. To calculate the width, you actually calculate the width of the text residing in that cell.

    use following

     boundingRect(with:options:attributes:context:)
    

    https://developer.apple.com/documentation/foundation/nsstring/1524729-boundingrect

    to calculate the width of a given string. So after calculating the returning the size the cell should be wrapping the text.

    Now come the second part, equal spacing between items. use interItemSpacing to define the spacing between each cell.

    0 讨论(0)
  • 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
        }
    }
    
    0 讨论(0)
提交回复
热议问题