UICollectionview Reuse Existing cell - ios

I want to generate collectionview with 100 number of cells, But it should not to be reallocate at every time of scrolling, But in my code its always creating cells newly.
any one help me to avoid this issue, please find my code below,
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return colorArray.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let colleCell: colorCell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! colorCell
colleCell.bgColor.backgroundColor = UIColor(red: colorArray[indexPath.row].valueForKey("Red") as! CGFloat/255, green: colorArray[indexPath.row].valueForKey("Green") as! CGFloat/255, blue: colorArray[indexPath.row].valueForKey("Blue") as! CGFloat/255, alpha: 1.0)
return colleCell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
let cell:colorCell = collectionView.cellForItemAtIndexPath(indexPath) as! colorCell
cell.layer.borderWidth = 2.0
cell.layer.borderColor = UIColor.whiteColor().CGColor
selectedColor = indexPath.row
sampleColorView.backgroundColor = UIColor(red: colorArray[indexPath.row].valueForKey("Red") as! CGFloat/255, green: colorArray[indexPath.row].valueForKey("Green") as! CGFloat/255, blue: colorArray[indexPath.row].valueForKey("Blue") as! CGFloat/255, alpha: 1.0)
self.view.backgroundColor = UIColor(red: colorArray[indexPath.row].valueForKey("Red") as! CGFloat/255, green: colorArray[indexPath.row].valueForKey("Green") as! CGFloat/255, blue: colorArray[indexPath.row].valueForKey("Blue") as! CGFloat/255, alpha: 0.7)
sampleColorView.layer.cornerRadius = 75
}
func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath)
{
let cell:colorCell = collectionView.cellForItemAtIndexPath(indexPath) as! colorCell
selectedIndex = -1;
cell.layer.borderWidth = 0.0
cell.layer.borderColor = UIColor.grayColor().CGColor
self.view.backgroundColor = UIColor.grayColor()
}

I think it's reused correctly, plz double check? But I suggest the way to set selected/deselected cell's style, you can override selected property of UICollectionViewCell.
class ColorCell : UICollectionViewCell{
override var selected: Bool{
didSet {
layer.borderWidth = selected ? 2 : 0
layer.borderColor = selected ? UIColor.whiteColor().CGColor : UIColor.grayColor().CGColor
}
/* your code */
}
and UICollectionViewDelegate implementation:
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
selectedColor = indexPath.row
sampleColorView.backgroundColor = /*Color*/
view.backgroundColor = /*Color*/
sampleColorView.layer.cornerRadius = 75
}
func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath) {
selectedIndex = -1;
self.view.backgroundColor = UIColor.grayColor()
}

Related

CollectionView scrolling changes the selected cells

CollectionView scrolling changes the selected cells. For example, there are 26 letters in my collectionView, items[0] is A, items[1] is B, ... items[25] is Z, now I selected items[1], it is B, and when I scroll the collectionView, items[1] will become deselected and there is another item will be selected. I know the problem is caused by Reuse but I don't know how to fix it properly even I use some solution that showed in google or StackOverflow.
My viewDidLoad:
collectionView.allowsMultipleSelection = false
My CollectionViewCell Class:
import UIKit
class AddCollectionViewCell: UICollectionViewCell {
}
My CollectionView Setting:
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return iconSet.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "iconCell", for: indexPath) as! IconCollectionViewCell
cell.iconImage.image = UIImage(named:iconSet[indexPath.row])
return cell
}
My CollectionView's didSelecteItemAt function:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) {
cell.backgroundColor = UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 0.3)
cell.backgroundView?.layer.cornerRadius = 5
}
My CollectionView's didDeSelecteItemAt function:
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) {
cell.backgroundColor = UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 0.0)
cell.backgroundView?.layer.cornerRadius = 5
}
}
You can achieve this by either store all selected item's index in separate array or you can manage separate property like isSelected in dictionary or array of custom class's objects whichever you used to fill your collectionview cells.
You can simply use array like below:
var arrIndex : [Int] = Int
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "iconCell", for: indexPath) as! IconCollectionViewCell
cell.iconImage.image = UIImage(named:iconSet[indexPath.row])
if arrIndex.contains(indexPath.item) {
cell.backgroundColor = UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 0.3)
}
else {
cell.backgroundColor = UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 0.0)
}
return cell
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if !arrIndex.contains(indexPath.item) {
arrIndex.append(indexPath.item)
collectionview.reloadData()
}
}
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
if arrIndex.contains(indexPath.item) {
arrIndex = arrIndex.filter { $0 != indexPath.item }
collectionview.reloadData()
}
}
You can try
var selectedIndex = 0 // set default or nil and check it's nullability before usage
//
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "iconCell", for: indexPath) as! IconCollectionViewCell
cell.iconImage.image = UIImage(named:iconSet[indexPath.row])
if indexPath.row == selectedIndex {
cell.backgroundColor = UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 0.3)
}
else {
cell.backgroundColor = UIColor(red: 255/255, green: 255/255, blue: 255/255, alpha: 0.0)
}
return cell
}
My CollectionView's didSelecteItemAt function:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
selectedIndex = indexPath.row
collectionview.reloadData()
}
My CollectionView's didDeSelecteItemAt function:
func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
// remove this
}

After reload collectionview,it always move to the first cell if also select the last cell

I have attached this image. You can see the problem here I have implemented the horizontal collection view where cells contains label. When we select the not visible items of the cell (after the first load 4 to 5 items are visible) and reload the cell it always moves to first visible cells.how should I handle the this problem?
func collectionView(
_ collectionView: UICollectionView,
cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier:
"profile_CollectionViewCell_city", for: indexPath as IndexPath) as!
profile_CollectionViewCell
cell.contentView.translatesAutoresizingMaskIntoConstraints = false
if ((self.data_array[indexPath.row] as! NSMutableDictionary)["title"] != nil) {
cell.city_name.text = ((self.data_array[indexPath.row] as! NSMutableDictionary)["title"] as? String)?.uppercased()
}
if (indexPath.row == selectedIndex) {
cell.city_name.textColor = UIColor(red: (0.0 / 255.0), green: (120.0 / 255.0), blue: (56.0 / 255.0), alpha: 1)
cell.city_name.font = UIFont(name: "Poppins-Bold", size: 14)
cell.lower_view.isHidden = false
} else {
cell.city_name.textColor = UIColor(red: (156.0 / 255.0), green: (156.0 / 255.0), blue: (156.0 / 255.0), alpha: 1)
cell.city_name.font = UIFont(name: "Poppins-Light", size: 14)
cell.lower_view.isHidden = true
}
return cell
}
func collectionView(
_ collectionView: UICollectionView,
numberOfItemsInSection section: Int) -> Int {
return data_array.count
}
func collectionView(
_ collectionView: UICollectionView,
layoutCollectionViewLayout: UICollectionViewLayout,
sizeForItemAtIndexPath: IndexPath) -> CGSize {
let size = ((self.data_array[indexPath.row] as!
NSMutableDictionary)["title"] as? String)?.size(withAttributes:
nil) ?? CGSize.zero
return size
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAtIndexPath: IndexPath) {
selectedIndex = indexPath.row
self.city_table.reloadData()
}

Selecting a Cell inside UICollectionView in a custom keyboard

I have a Cell comprising of an Image View inside a UI Collection View in a custom keyboard extension. Everything looks good except when I try to select an item in the collection view nothing happens. Any idea/suggestions?
Yes, I have attached delegates.
override func viewDidLoad() {
super.viewDidLoad()
self.collectionView.delegate = self
self.collectionView.dataSource = self
self.collectionView.allowsSelection = true
self.collectionView.allowsMultipleSelection = false
}
//This works
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "cell",for: indexPath)
cell.backgroundColor = #colorLiteral(red: 0, green: 0.4117647059, blue: 0.8509803922, alpha: 1)
return cell
}
//This doesnt
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "cell",for: indexPath)
cell.backgroundColor = #colorLiteral(red: 1, green: 1, blue: 1, alpha: 1)
}
Any idea/Suggestions?
EDIT:
Uploaded my code to github for better suggestions :)

Tickmark image should be Inserted/deleted on every cell selection/deselection in collection view

I have enabled the multiple selection.And i am getting succesfull in changing the color of the cell when i tap it.But i also want to add a tickmark image to the cell when it is selected and removing this image when i deselect the cell.I am new to swift programming please solve this problem.here is my collection view delegate and data source
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return marrCategoriesInfo.count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionVieww .dequeueReusableCellWithReuseIdentifier("myCell", forIndexPath: indexPath)as! CollectionViewCell
for _ in 0 ..< marrCategoriesInfo.count {
cell.backgroundColor = self.colorWithHexString(arrColors[indexPath.row])
if (arrColors.count < marrCategoriesInfo.count)
{
arrColors.appendContentsOf(arrColors)
}
}
cell.labellpersons.text = marrCategoriesInfo[indexPath.row] as? String
cell.labellpersons.textColor = UIColor .whiteColor()
element = self.marrCategoriesInfo[indexPath.row] as! NSString
if UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiom.Pad
{
stringSize = element.sizeWithAttributes([NSFontAttributeName: UIFont.systemFontOfSize(25)]) as CGSize
cell.labellpersons.sizeThatFits(stringSize)
cell.layer.borderWidth = 2;
cell.layer.borderColor = UIColor .blackColor().CGColor
cell.layer.cornerRadius = 35;
cell.labellpersons.textAlignment = .Center
}
else
{
stringSize = element.sizeWithAttributes([NSFontAttributeName: UIFont.systemFontOfSize(12.0)]) as CGSize
cell.labellpersons.sizeThatFits(stringSize)
cell.layer.borderWidth = 1;
cell.layer.borderColor = UIColor .blackColor().CGColor
cell.layer.cornerRadius = 25;
cell.labellpersons.textAlignment = .Center
}
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
let acelll = collectionVieww.cellForItemAtIndexPath(indexPath)
acelll?.backgroundColor = UIColor (red: 49/255, green: 30/255, blue: 49/255, alpha:1.0)
acelll?.layer.borderWidth = 2.0
acelll?.layer.borderColor = UIColor .whiteColor() .CGColor
IndexValue .addObject(indexPath.row)
print("indexavalueis",IndexValue)
}
internal func collectionView(collectionView: UICollectionView, didDeselectItemAtIndexPath indexPath: NSIndexPath)
{
let acell = collectionView .cellForItemAtIndexPath(indexPath)
acell?.backgroundColor = self.colorWithHexString(arrColors[indexPath.row])
acell!.layer.borderWidth = 1.0;
acell!.layer.borderColor = UIColor .blackColor() .CGColor
IndexValue.removeObject(indexPath.row)
print(IndexValue)
}

UICollectionView and selected UICollectionViewCell

I'm trying to do a simple UICollectionView with a custom cell composed of an UIImageView and an UIView above.
When a cell is not selected, the UIView on the top of the cell have is backgroundColor property set to UIColor(red: 1, green: 1, blue: 1, alpha: 0.5).
I have issues with the selection. The collectionView:didSelectItemAtIndexPath: method is called but when I change the UIView described previously, nothing happen.
Here is the code of my collectionView :
class TestCollectionViewController: UICollectionViewController
{
var items = [1, 2, 3]
let cellId = "Cell"
override func viewDidLoad()
{
self.collectionView.allowsMultipleSelection = true
self.collectionView.delaysContentTouches = false
}
override func collectionView(collectionView: UICollectionView!, numberOfItemsInSection section: Int) -> Int
{
return items.count
}
override func collectionView(collectionView: UICollectionView!, cellForItemAtIndexPath indexPath: NSIndexPath!) -> UICollectionViewCell!
{
var cell = collectionView.dequeueReusableCellWithReuseIdentifier(cellId,
forIndexPath: indexPath) as TestingCollectionViewCell
let item = items[indexPath.row]
cell.imageView.image = UIImage(named: "img")
cell.overlayView.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.5)
return cell
}
override func collectionView(collectionView: UICollectionView!, didSelectItemAtIndexPath indexPath: NSIndexPath!)
{
var cell = collectionView.dequeueReusableCellWithReuseIdentifier(cellId,
forIndexPath: indexPath) as TestingCollectionViewCell
cell.overlayView.backgroundColor = UIColor.clearColor()
}
override func collectionView(collectionView: UICollectionView!, didDeselectItemAtIndexPath indexPath: NSIndexPath!)
{
var cell = collectionView.dequeueReusableCellWithReuseIdentifier(cellId,
forIndexPath: indexPath) as TestingCollectionViewCell
cell.overlayView.backgroundColor = UIColor(red: 1, green: 1, blue: 1, alpha: 0.5)
}
}
If this snippet is not enough, here is my project
You should not be dequeuing a new cell in didSelectItemAtIndexPath (or in didDeselect either) -- this is creating (or reusing) a new cell, not getting the one you selected. Use this instead,
var cell = collectionView.cellForItemAtIndexPath(indexPath)
To me the following code worked better (the code of rdelmar crashed sometimes, which might be a bug? in Swift):
(collectionView.cellForItemAtIndexPath(indexPath) as myCollectionViewCellType).uiBackground?.backgroundColor = UIColor.blackColor()
Edit: I forgot to mention: My collectionView-Items are based on their own class to which I cast. uiBackground is an element of that class
Swift 3.0
let cell = collectionView.cellForItem(at: indexPath)
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
//saving index path of the image loaded from imageproperty_array
selected_imagepath = imageproperty_array[indexPath.row] as String
//saving index of the selected cell item as Int
selected_imageindex = indexPath.row
}

Resources