Reputation: 1184
I need to change collectionview cell width according to its label text like this
for that i have given collectionview constraints
top, leading, trailing, = 10 height = 80
in cell i have placed label inside uiview, i have placed uiview because i need to give corner radious
and code
class SearchFilterVC: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
var textArray = ["hbdhwebhj", "behgwfhjewgbkfjbe", "hbhjs", "bdhsbfhegu", "gwdgyqwuguq"]
@IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 5
self.collectionView.collectionViewLayout = layout
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return textArray.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "SearchFilterCollectionViewCell", for: indexPath as IndexPath) as! SearchFilterCollectionViewCell
cell.textLabel.text = textArray[indexPath.row]
return cell
}
}
edit:
o/p
how to over come from this issue, please do help with code
Upvotes: 2
Views: 5157
Reputation: 20379
All items in your collectionView are taking the exact same size because you have specified layout.itemSize
for your collectionView's flow layout
remove layout.itemSize = CGSize(width: self.collectionView.frame.size.width / 2, height: 80)
Other issues in code:
layout.invalidateLayout()
is unnecessary in ViewDidLoad
if let layout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
to set minimumInteritemSpacing
and minimumLineSpacing
is unnecessary, in a statement just above it you have created let layout = UICollectionViewFlowLayout()
why dont you simply set minimumInteritemSpacing
and minimumLineSpacing
there itself? Why use additional if let
?Simply write
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 5
self.collectionView.collectionViewLayout = layout
You need not specify item size, Collection view flow layout is set to be horizontal in nature, so by default each item will take the same height as the collection view height and if you have only one label inside the cell and if you have set autolayout constraint properly, label's intrinsic content size will ensure cell gets proper width
And forwhatever reason if you decide to wrap the label inside a UIView
logic above holds good, as long as you set the label's autolayout constraint right, lablel's intrinsic content size will set the width of the containerView and which will in turn contribute to set the cell's width appropriately,
Here cell has background color of red, container view has orange and label has no background color, I have added leading and trailing spacing between cell and view as 10, and label and container view has leading and trailing space as 5
EDIT:
As OP is asking for constraints between container view, label and cell, I am updating answer to reflect the same
Clearly
- - - - - - - - - - - - Cell - - - - - - - - - - - - - - - -
| - - - - - - - - Container View - - - - - - - - |
| | |5 | |
|-10- |-5- Label -5-| -10- |
| | |5 | |
| - - - - - - - - - - - - - - - - - - - - - - - - - |
| |
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
You can add top and bottom constraint between cell and conatiner if you need, but I have kept container view vertically center to cell
How it works?
Label has intrinsic content-size which it gets from the text set to it, View does gets its intrinsic size based on the size of its subview, because there are no subviews in your container view, it gets its size from label and clearly whatever the size label returns view adds 10 to width and 10 to height ( 5 leading, 5 trailing, 5 top and 5 bottom) finally cell gets its size from its subviews, because there is only one subview (container view) it gets width from container view and for height it gets its height from collection view (as subviews dont provide enough data to calculate its height)
And if for some reason (might be because of some other constraints you have set knowingly / unknowingly like adding width constraint on container view) label is not taking its intrinsic content size correctly, you can always set setContentCompressionResistancePriority
and setContentHuggingPriority
on label to high in your cell's awake from nib
override func awakeFromNib() {
super.awakeFromNib()
self.label.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
self.label.setContentHuggingPriority(.defaultHigh, for: .horizontal)
}
Though this shouldnt be needed in usual case, if this is needed to get correct intrinsic size, there must be some other constraints which are preventing the label to take its proper implicit intrinsic content size, if I were in your position would rather check and fix it first. Nonetheless cant debug further with limited code you have provided.
EDIT 2:
Did not realize that OP is using custom instance of UICollectionViewFlowLayout
and has not set estimatedItemSize
property to automaticSize
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumInteritemSpacing = 0
layout.minimumLineSpacing = 5
layout.estimatedItemSize = UICollectionViewFlowLayout.automaticSize
self.collectionView.collectionViewLayout = layout
Upvotes: 6