Home > front end >  How to make collectionViewCell have a different width content
How to make collectionViewCell have a different width content

Time:11-20

i create a tab menu using collectionViewCell but, i have 5 cell menu. but the name in cell got truncate, i want if there is a long name label. the container view in collectionViewCell should grow.

truncate label

i try to use the collectionViewFlowLayout estimatedItemSize, but the result is. the cell become ugly not like before

estimatedItemSize

How to make the collectionViewCell grow size but maintain full width.

this is my setup for my collectionViewCell

private let padding: CGFloat = 8

override init(frame: CGRect) {
        super.init(frame: frame)
        configure()
    }
    
required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
}

private func configure() {
        addSubview(selectionView)
        selectionView.addSubview(titleLabel)

        NSLayoutConstraint.activate([
            selectionView.topAnchor.constraint(equalTo: topAnchor, constant: padding),
            selectionView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 4),
            selectionView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -4),
            selectionView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -padding),

            titleLabel.topAnchor.constraint(equalTo: selectionView.topAnchor, constant: padding),
            titleLabel.leadingAnchor.constraint(equalTo: selectionView.leadingAnchor, constant: 4),
            titleLabel.trailingAnchor.constraint(equalTo: selectionView.trailingAnchor, constant: -4),
            titleLabel.bottomAnchor.constraint(equalTo: selectionView.bottomAnchor, constant: -padding)
        ])
    }

and this is my setup for my collectionView

private func setupCollectionView() {
        let layout = UICollectionViewFlowLayout()
        layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize

        collectionView = UICollectionView(frame: bounds, collectionViewLayout: layout)
        collectionView.delegate = self
        collectionView.dataSource = self
        collectionView.register(TabCollectionViewCell.self, forCellWithReuseIdentifier: TabCollectionViewCell.cellID)

        [notificationLabel, collectionView].forEach { view in
            guard let view = view else { return }
            view.translatesAutoresizingMaskIntoConstraints = false
            addSubview(view)
        }

        NSLayoutConstraint.activate([
            notificationLabel.topAnchor.constraint(equalTo: topAnchor, constant: 8),
            notificationLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding),
            notificationLabel.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -padding),

            collectionView.topAnchor.constraint(equalTo: notificationLabel.bottomAnchor, constant: 8),
            collectionView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: padding),
            collectionView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -padding),
            collectionView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8)
        ])

    }

extension HeaderCollectionView: UICollectionViewDelegateFlowLayout {

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: collectionView.bounds.width / CGFloat(items.count), height: collectionView.bounds.height)
    }

    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 0
    }

}

CodePudding user response:

Create a String extension method that will calculate the width of the string and after that use that in your delegate method:

Step 1: Calculate the string width

extension String {
    func getStringwidth(height: CGFloat, font: UIFont) -> CGFloat {
        let constraintRect = CGSize(width: .greatestFiniteMagnitude, height: height)
        let boundingBox = self.boundingRect(with: constraintRect, options: [.usesLineFragmentOrigin, .usesFontLeading], attributes: [NSAttributedString.Key.font: font], context: nil)
        return boundingBox.width
    }
}

Step 3: Calculate the max width

func calculateMaxWidth()-> CGFloat {
        // my Data shource array Data
        var allSize: [CGFloat] = []
        arrayData.forEach{
            allSize.append($0.widthWithConstrainedHeight(height: 30,
                                                         font: UIFont.systemFont(ofSize: 17)))
        }
        return allSize.max() ?? 0.0
        
    }

Step 2: Call the max from viewdidLoad

    override func viewDidLoad() {
    super.viewDidLoad()
    
    let layout = UICollectionViewFlowLayout()
    layout.estimatedItemSize =  CGSize(width: calculateMaxWidth(), height: 30)

Adjust based on your requirement.

Output: enter image description here

  • Related