CollectionView Dynamic cell height swift

前端 未结 3 1813
傲寒
傲寒 2020-12-08 19:37

Im trying to create a collection view with cells displaying string with variable length.

Im using this function to set cell layout:

 func collectionV         


        
相关标签:
3条回答
  • 2020-12-08 19:57

    While the answer above may solve your problem, it establishes a pretty crude way of assigning each cells height. You are being forced to hard code each cell height based on some estimation. A better way of handling this issue is by setting the height of each cell in the collectionview's sizeForItemAtIndexPath delegate method.

    I will walk you through the steps on how to do this below.

    Step 1: Make your class extend UICollectionViewDelegateFlowLayout

    Step 2: Create a function to estimate the size of your text: This method will return a height value that will fit your string!

    private func estimateFrameForText(text: String) -> CGRect {
        //we make the height arbitrarily large so we don't undershoot height in calculation
        let height: CGFloat = <arbitrarilyLargeValue>
    
        let size = CGSize(width: yourDesiredWidth, height: height)
        let options = NSStringDrawingOptions.UsesFontLeading.union(.UsesLineFragmentOrigin)
        let attributes = [NSFontAttributeName: UIFont.systemFontOfSize(18, weight: UIFontWeightLight)]
    
        return NSString(string: text).boundingRectWithSize(size, options: options, attributes: attributes, context: nil)
    }
    

    Step 3: Use or override delegate method below:

    func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
        var height: CGFloat = <someArbitraryValue>
    
       //we are just measuring height so we add a padding constant to give the label some room to breathe! 
        var padding: CGFloat = <someArbitraryPaddingValue>
    
        //estimate each cell's height
        if let text = array?[indexPath.item].text {
             height = estimateFrameForText(text).height + padding
        }
        return CGSize(width: yourDesiredWidth, height: height)
    }
    
    0 讨论(0)
  • 2020-12-08 19:59

    You can dynamically set the frame of the cell in the cellForItemAtIndexPath function, so you can customize the height based on a label if you disregard the sizeForItemAtIndexPath function. With customizing the size, you'll probably have to look into collection view layout flow, but hopefully this points you in the right direction. It may look something like this:

    class CollectionViewController: UICollectionViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    
        var array = ["a","as","asd","asdf","asdfg","asdfgh","asdfghjk","asdfghjklas","asdfghjkl","asdghjklkjhgfdsa"]
        var heights = [10.0,20.0,30.0,40.0,50.0,60.0,70.0,80.0,90.0,100.0,110.0] as [CGFloat]
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
    
        override func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int {
            return 1
        }
    
        override func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
            return array.count
        }
    
        override func collectionView(collectionView: UICollectionView,
            cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
    
                let cell = collectionView.dequeueReusableCellWithReuseIdentifier("CellID", forIndexPath: indexPath) as Cell
                cell.textLabel.text = array[indexPath.row]
                cell.textLabel.sizeToFit()
    
                // Customize cell height
                cell.frame = CGRectMake(cell.frame.origin.x, cell.frame.origin.y, cell.frame.size.width, heights[indexPath.row])
                return cell
        }
    
        func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
            return CGSizeMake(64, 64)
        }
    }
    

    which gives dynamic heights like so enter image description here

    0 讨论(0)
  • 2020-12-08 20:08

    In Swift 3, use the below method:

    private func updateCollectionViewLayout(with size: CGSize) {
        var margin : CGFloat = 0;
        if isIPad {
            margin = 10
        }
        else{
            margin = 6
            /* if UIDevice.current.type == .iPhone6plus || UIDevice.current.type == .iPhone6Splus || UIDevice.current.type == .simulator{
             margin = 10
    
             }
             */
        }
        if let layout = menuCollectionView.collectionViewLayout as? UICollectionViewFlowLayout {
            layout.itemSize = CGSize(width:(self.view.frame.width/2)-margin, height:((self.view.frame.height-64)/4)-3)
            layout.invalidateLayout()
        }
    }
    
    0 讨论(0)
提交回复
热议问题