Swift reconfigure collectionview cells - swift

so I am trying to change the background color of the collection view cell that is clicked, however, when I call the CollectionView.reloadData() method the backgrounds don't change. I am thinking that reloading the data only checks for adding and deleting cells, but does not actually call the configure function for each cell again. I was wondering how I can reconfigure these cells so that the background color can change for the selected cell. Thanks for the help in advance!
This is the method that I call:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
...
bagCollectionView.reloadData()
}

Instead of calling reloadData, you can try:
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath)
cell?.backgroundColor = yourColor
}

Even though you do your logic in did select by finding a cell or implement logic in didSelectItemAt and didDeSelectItemAt, I suggest you should store the Index. Due to reusability of cell, there is chance that selected cell do not show color on scroll or if you have large number or records.
So save index in array(for multiple selections) or a single variable(single selection) and manage logic for the same.
For example:
cell.backgroundColor = selectedIndex == indexPath.item ? .red : .yellow

Related

How to customize the 1st and 3rd cell in a custom collection view

I have a ui collection view returning custom cells of posted images - I want to round the corners of only the 1st and 3rd cell in the top row returned and nothing else. I checked the indexPath but is the same for multiple cells so it rounds multiple rows of cells.
I would add the customization inside willDisplayCell :
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if indexPath.row == 1 || indexPath.row == 3 {
cell.roundCorners() // or whatever code you use for this.
}
}

How to check if the collection view cell is clicked

I want to check if the collectionview cell is clicked
func collectionView(_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath) {
//code..
}
Well you already have the key to your problem, it's just you don't know how to use it.
So every UIKit element has it's own delegate which is called when some event occurs.
In case of collection view, whenever cells are clicked didSelectItemAt will be called.
Here is an example
func collectionView(_ collectionView: UICollectionView,
didSelectItemAt indexPath: IndexPath) {
print("Cell \(indexPath.row + 1) clicked")
}
Considering above code just imagine you have 5 cells,
Whenever you click on any cell the above code will execute.
If you click on Third cell it will print: Cell 3 clicked
And if you don't click any cell nothing will happen.
Hope now everything is clear, Happy coding :)

removal of spacing between specific UICollectionViewCells

I am using UICollectionFlowLayout to establish minimumLineSpacing between collectionItems, I am trying to find a way to set the spacing to zero for some cells so there is no spacing, i.e they appear to be 'merged' while leaving others with their spaces intact, is it possible to make alterations in the cellForItemAt method for example to achieve this?
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "customColCell", for: indexPath) as! customColCell
if indexPath.row == 5 {
self.minimumLineSpacing = 100 // -- this does not result in an individual change...
}
cell.textLabel.text = indexPath.row.description
return cell
}
is it possible to make alterations in the cellForItemAt method for example to achieve this
No. What you're asking to do is not how a UICollectionViewFlowLayout behaves by default. You will need to write a collection view layout subclass.

Custom property collectionviewcell

I use this code to show a collection of images, which are scrollable. However, I would like to add a property to make it possible to identify each cell or image in this case. I want a property to every cell that can hold a string.
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "PalletsCollectionViewCell", for: indexPath) as! PalletsCollectionViewCell
cell.imgImage.image = imageArray[indexPath.row];
return cell;
}
Haven't found anything while reading the swift documentation.
What I want to do is to add events to the cells. If the user touches a cell, a function will be called. This function performs an API request with the property value as parameter.

Do I need to use the numberOfItemsInSection function if setting the number of items in storyboard?

There are a few posts on UICollectionViews and as a general concept I understand UICollectionViews are similar to how TableViews are implemented. There are a few posts on this topic already.
How to make a simple collection view with Swift
I'm using a UICollectionView to layout 8 cells for essentially decorative purposes...just as a container to hold a few images for a page. The images aren't meant to be interactive eg. a shopping cart.
My question is whether I need to implement the function below (and other similar functions) if i'm laying out my cells on the storyboard.
// tell the collection view how many cells to make
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.items.count
}
I have 8 cells within a UICollectionView that i have configured on the storyboard (this collection view is a view on a UIViewController) and each UICollectionViewCell has an image view with in. I have laid this all out on the storyboard.
I also don't want to put an image in each cell. Just a certain number of cels eg. cells 2,3,5 and 8.
So what I was going to do is create a class that extends UIControllerViewCell and create an IBOutlet for the image view and then in the interface builder reference the custom cell class.
And I think - but could do with some advice - then all I need to do is use the function below and because I only want to populate certain cells I can use an if statement for index path when it's 2,3,5 and 8:
// make a cell for each cell index path
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if(indexPath == 2 || 3 || 5|| 8)
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath as IndexPath) as! MyCollectionViewCell
// Use the outlet in our custom class to get a reference to the UILabel in the cell
cell.image = self.items[indexPath.item]
return cell
}
}
Thanks.
cellForItemAt must return value (which is UICollectionViewCell instance in this case), but you are free to set image of certain cells to nil (AKA no image)
eg:
// make a cell for each cell index path
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier, for: indexPath) as! MyCollectionViewCell
if([2,3,5,8].contains(indexPath.row))
{
// Use the outlet in our custom class to get a reference to the UIImageView in the cell
cell.myImageView.image = self.items[indexPath.row]
} else {
cell.myImageView.image = nil
}
return cell
}
Sounds like you are asking about a static UICollectionViewController which is not possible. You will make a single prototype cell in the storyboard and link the IBOutlets with the desired class. You will also need to implement the data source and delegate methods for UICollectionView. Just hide the image where you don't want to show it based on the index.