CollectionView First And Last Cell remains selected - swift

i am using a collectionView which is selectable, and when a user selects the first then the last cell both cells remain selected for some reason idk why.
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
if (collectionView == self.categoryCollectionView)
{
let cell = collectionView.cellForItem(at: indexPath) as? ChannelsCategoryCell
cell?.triangleIndicatorView.isHidden = false
cell?.categoryLabel.textColor = UIColor.init(named: "ActiveSymbol")
loadChannelList()
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath)
{
if (collectionView == self.categoryCollectionView)
{
let cell = collectionView.cellForItem(at: indexPath) as? ChannelsCategoryCell
cell?.triangleIndicatorView.isHidden = true
cell?.categoryLabel.textColor = UIColor.init(named: "InactiveCategoryText")
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellIdentifier, for: indexPath) as! CollectionViewCell
if selectedIndex == indexPath.item {
cell.backgroundColor = .blue
} else {
cell.backgroundColor = .clear
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedIndex = indexPath.item
collectionView.reloadData()
}

Related

Change `numberOfItemsInSection` parameter of a collection view

How is it possible to change numberOfItemsInSection parameter of a collection view?
I have made a basic setup of a collection view. And now I try to make a button, that changes the amount of items in it.
The general setup is a standard one:
func numberOfSections(in collectionView: UICollectionView) -> Int {
1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
arrayA.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.imageView.image = arrayA[indexPath.item][0].image
return cell
}
The question is - how to configure a button, so it could change numberOfItemsInSection parameter from current arrayA.count to some other (e.x. arrayB.count)?
Example:
You could take a common a flag to toggle between arrayA and arrayB. When the button is clicked as
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return isUseArrayA ? arrayA.count : arrayB.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.imageView.image = isUseArrayA ? arrayA[indexPath.item][0].image : arrayB[indexPath.item][0].image
return cell
}
#IBAction func changeSource(sender: UIButton) {
if sender.tag == 0 {
isUseArrayA = true
sender.tag = 1
} else {
sender.tag = 0
isUseArrayA = false
}
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.collectionView.reloadData()
}
}
// No need of numberOfSection because it is bydefault 1.
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
arrayA.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.imageView.image = arrayA[indexPath.item][0].image
return cell
}
#IBAction func changeArrayCount(sender: UIButton) {
arrayA.append(image)
DispatchQueue.main.async { [weak self] in
guard let self = self else { return }
self.collectionView.reloadData()
}
}

Save Updated Order Of CollectionView Images To UserDefaults - Swift

I have a collectionview which loads images and displays them. I have implemented gestures so that a person can hold and reorder the images, however the order does not save. Is there a way to save this order through User Defaults? If so, where would I implement this to save the order and load again? Below is my code for collectionView. Thanks in advance, any help is much appreciated!
func collectionView(_ imageCollection: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.posts.count
}
func collectionView(_ imageCollection: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = imageCollection.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! ImageCollectionViewCell
let post = self.posts[indexPath.item]
cell.imageView.sd_setImage(with: URL(string: post.imageURL))
return cell
}
func collectionView(_ imageCollection: UICollectionView, didSelectItemAt indexPath: IndexPath) {
switch mMode {
case .view:
imageCollection.deselectItem(at: indexPath, animated: true)
case .select:
dictionarySelectedIndexPath[indexPath] = true
}
}
func collectionView(_ imageCollection: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
if mMode == .select {
dictionarySelectedIndexPath[indexPath] = false
}
}
func collectionView(_ collectionView: UICollectionView, canMoveItemAt indexPath: IndexPath) -> Bool {
return true
}
func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let item = posts.remove(at: sourceIndexPath.row)
posts.insert(item, at: destinationIndexPath.row)
}
Base on your example code, I think it looks fine just missing to reload. :)
func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let item = posts.remove(at: sourceIndexPath.row)
posts.insert(item, at: destinationIndexPath.row)
collectionView.reloadData() //the missing code
}

UICollectionViewLayout Not working with UIImage in Swift 5 and Xcode 11

Please check this attached code and screen short. It's work fine when I set the color of container view but when I add UIImage in cell then it's not working. I changed the imageview content mode but it's not working.
class ViewController: UIViewController {
#IBOutlet weak var segColumn: UISegmentedControl!
#IBOutlet weak var collectionView: UICollectionView!
fileprivate var items: [UIImage] = [ // My images ]
override func viewDidLoad() {
super.viewDidLoad()
self.setup()
}
}
extension ViewController: UICollectionViewDataSource{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return items.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.imgCell.image = items[indexPath.row]
cell.imgCell.contentMode = .scaleAspectFill
cell.contentView.backgroundColor = .red
return cell
}
}
extension ViewController: UICollectionViewDelegateFlowLayout{
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: (collectionView.bounds.width/3 - 2), height: (collectionView.bounds.width/3))
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 2
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 2
}
}
Please try this solution. I think there are some changes from Xcode 11.
Change the CollectionView Estimate Size to None then it will work.
it is probably because the red is dominating over the image
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.imgCell.image = items[indexPath.row]
cell.imgCell.contentMode = .scaleAspectFill
cell.contentView.backgroundColor = .red
return cell
}
try:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell
cell.contentView.backgroundColor = .red
cell.imgCell.image = items[indexPath.row]
cell.imgCell.contentMode = .scaleAspectFill
return cell
}

UICollectionView Cell not changing upon selecting

In my project, I have a UICollectionView. In the UICollectionView, I have a custom cell.
I am able to print the cell value when it is selected within "didSelectItemAt", however, if I try to edit the cell in any way within this method, it does not change.
I'm sure I'm missing something, any help would be appreciated!
#IBOutlet weak var collectionView: UICollectionView!
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return statValues.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "customCollectionViewCell", for: indexPath) as! customCollectionViewCell
cell.statLabel.text = statHeaders[indexPath.row]
cell.statLabel.textColor = UIColor(red:0.31, green:0.31, blue:0.31, alpha:1.0)
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "customCollectionViewCell", for: indexPath) as! customCollectionViewCell
print(cell.statLabel.text)
cell.backgroundColor = UIColor.yellow
collectionView.reloadData()
}
When user selects a cell, the code is correctly printing the value of the indexPath, however the backgroundColor does not change.
My guess would be that you are creating a new instance of cell instead of using the one in the collectionView
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// Change this line
let cell = collectionView.cellForItemAtIndexPath(indexPath: indexPath)
print(cell.statLabel.text)
cell.backgroundColor = UIColor.yellow
collectionView.reloadData()
}
Also, you should probably keep an external data model for your source of truth. If you have enough collectionViews that requires scrolling, when you scroll offscreen, your cells will be reused in a random order causing cells that you did not click to be yellow.
Create a seperate array such as
var selectedStatHeaders: Set<Int>()
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "customCollectionViewCell", for: indexPath) as! customCollectionViewCell
cell.statLabel.text = statHeaders[indexPath.row]
cell.statLabel.textColor = UIColor(red:0.31, green:0.31, blue:0.31, alpha:1.0)
// Reset/configure cell each reload
if selectedStatHeaders.contains(indexPath.row) { // Can also make this into a ternary
cell.backgroundColor = UIColor.yellow
} else {
cell.backgroundColor = UIColor.whit
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedStatHeaders.insert(indexPath.row)
collectionView.reloadItemsAtIndexPath(indexPath: indexpath)
}
Hmm... Doesn't make sense if the code is able to print but the background doesn't change color. Do you mean changing back from yellow to white? Anyway, just a hunch but I suspect it's because you are calling collectionView.reloadData() after your set the backgroundColor change.
https://developer.apple.com/documentation/uikit/uicollectionview/1618078-reloaddata
This causes the collection view to discard any currently visible
items (including placeholders) and recreate items based on the current
state of the data source object.

UICollectionView keeps crashing unless i set indexpath.items = 1

Hi I have two codes for someone reason 1 works while the other doesn't can someone please explain why? The first function works, while the second doesn't. I'm trying to generate one cell as the type PayNowCell and every cell after that as the CheckOutCell type. However, it will only allow me to put the first cell as a CheckOutCell, the second as a PayNowCell, and every following cell as a CheckOutCell. Thanks!!! Error is index is out of bounds. And it points to this line
cell.item = checkout[indexPath.item].
Essentially i have a dynamic array checkout[] and im just trying to insert a description cell called paynow ontop of each checkoutcell while the checkout[] grows and shrinks
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 1 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "paynow", for: indexPath) as! PayNowCell //init cells
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! CheckoutCell //init cells
cell.item = checkout[indexPath.item]
return cell
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "paynow", for: indexPath) as! PayNowCell //init cells
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! CheckoutCell //init cells
cell.item = checkout[indexPath.item]
return cell
}
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return (checkout.count + 1) //init number of cells
}
Try this array for manage your collection view
var array = [0,[]]
then add
array[1] = [your array for index 1]
You can add the section for manage multi-cell inside your collection view:-
func numberOfSections(in collectionView: UICollectionView) -> Int{
return (array[section] as AnyObject).count
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return array[1].count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "paynow", for: indexPath) as! PayNowCell //init cells
return cell
}else{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! CheckoutCell //init cells
let checkout = array[1] // pass here array
guard checkout.count != 0 else {
return cell
}
cell.item = checkout[indexPath.item]
return cell
}
}