Dynamic cell width of UICollectionView depending on label width

前端 未结 7 1335
别跟我提以往
别跟我提以往 2020-11-28 02:44

I have a UICollectionView, that loads cells from reusable cell, which contains label. An array provides content for that label. I can resize label width depending on content

相关标签:
7条回答
  • 2020-11-28 02:56

    In sizeForItemAtIndexPath return the size of the text

    - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath{
    
        return [(NSString*)[arrayOfStats objectAtIndex:indexPath.row] sizeWithAttributes:NULL];
    }
    
    0 讨论(0)
  • 2020-11-28 03:00

    Swift 4.2+

    Principle is:

    1. Make sure delegation is set up (e.g. collectionView.delegate = self)

    2. Implement UICollectionViewDelegateFlowLayout (it contains necessary method signature).

    3. Call collectionView...sizeForItemAt method.

    4. No need to bridge-cast String to NSString to call size(withAttributes: method. Swift String has it out of the box.

    5. Attributes are the same you set for (NS)AttributedString, i.e. font family, size, weight, etc. Optional parameter.


    Sample solution:

    extension ViewController: UICollectionViewDelegateFlowLayout {
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
            return "String".size(withAttributes: nil)
        }
    }
    

    But you would most likely want to specify concrete string attributes respective to your cell, hence final return would look like:

    extension ViewController: UICollectionViewDelegateFlowLayout {
        func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
            // dataArary is the managing array for your UICollectionView.
            let item = dataArray[indexPath.row]
            let itemSize = item.size(withAttributes: [
                NSAttributedString.Key.font : UIFont.boldSystemFont(ofSize: 14)
            ])
            return itemSize
        }
    }
    

    Why you SHOULD NOT use UILabel to calculate the size? Here's the suggested solution:

    let label = UILabel(frame: CGRect.zero)
    label.text = textArray[indexPath.item]
    label.sizeToFit()
    

    Yes, you get same result. It looks simplistic and may seem as a go-to solution. But it's improper because: 1) it's expensive, 2) overhead and 3) dirty.

    It's expensive because UILabel is a complex UI object, which is being created on every iteration whenever your cell is about to show even though you don't need it here. It's an overhead solution because you only need to get size of a text, but you go as far as to create a whole UI object. And it's dirty for that reason.

    0 讨论(0)
  • 2020-11-28 03:03

    In Swift 3

    let size = (arrayOfStats[indexPath.row] as NSString).size(attributes: nil)
    
    0 讨论(0)
  • 2020-11-28 03:04

    I have found a small trick for swift 4.2

    For dynamic width & fixed height:

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
            let label = UILabel(frame: CGRect.zero)
            label.text = textArray[indexPath.item]
            label.sizeToFit()
            return CGSize(width: label.frame.width, height: 32)
        }
    

    For dynamic height & fixed width:

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
                let label = UILabel(frame: CGRect.zero)
                label.text = textArray[indexPath.item]
                label.sizeToFit()
                return CGSize(width: 120, height: label.frame.height)
            }
    
    0 讨论(0)
  • 2020-11-28 03:12

    //add in view didload

    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
        [layout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
        layout.estimatedItemSize = CGSizeMake(self.breadScrumbCollectionView.frame.size.width, 30); 
    self.breadScrumbCollectionView.collectionViewLayout = layout;
    
    0 讨论(0)
  • 2020-11-28 03:16

    Swift 4

    let size = (arrayOfStats[indexPath.row] as NSString).size(withAttributes: nil)
    
    0 讨论(0)
提交回复
热议问题