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.
i try to use the collectionViewFlowLayout estimatedItemSize, but the result is. the cell become ugly not like before
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.