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
}
Related
I want to display UICollectionView inside static TableViewCell
I have a static TableViewCell that contains CollectionView. Well, the problem is that, in my opinion, code looks good but when I launch program, TableViewCell doesn't show me CollectionView. I'm a little bit confused, so I will be so happy if you help me. Thanks
TableViewController Class:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var Cell = tableView.dequeueReusableCell(withIdentifier: "Action")
switch indexPath.section {
case 0:
tableView.register(ScheduleCell.self, forCellReuseIdentifier: "Schedule")
Cell = tableView.dequeueReusableCell(withIdentifier: "Schedule") as! ScheduleCell
case 1:
return Cell!
case 2:
tableView.register(MarksCell.self, forCellReuseIdentifier: "Marks")
Cell = tableView.dequeueReusableCell(withIdentifier: "Marks") as! MarksCell
default:
Cell = tableView.dequeueReusableCell(withIdentifier: "Action") as! ActionCell
}
return Cell!
}
ActionCell:
extension ActionCell: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 3
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "ActionCell", for: indexPath) as! ActionsCollectionViewCell
var Labels = ["РАСПИСАНИЕ", "ДОМАШНИЕ ЗАДАНИЯ", "ОЦЕНКИ"]
var Icons = ["Safari", "DZ", "Rating"]
var Colors = [UIColor.init(red: 26/255, green: 196/255, blue: 234/255, alpha: 1),
UIColor.init(red: 251/255, green: 143/255, blue: 25/255, alpha: 1),
UIColor.init(red: 251/255, green: 25/255, blue: 118/255, alpha: 1)]
cell.Title.text = Labels[indexPath.item]
cell.Icon.image = UIImage.init(named: Icons[indexPath.item])
cell.Button.backgroundColor = Colors[indexPath.item]
return cell
}
}
Also, I have to notice that in Storyboard i mentioned all classes and ReuseIDs
If you're using 'UITableView' with Static Cells as a content you don't need to implement 'tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)' everything can be defined in Storyboard.
Here's how the UITableViewController would look like in storyboard, using custom cells (TableCell, CollectionCell) both for table and collection view, and having 'UITableViewCell'
act as a data source for containing 'UICollectionView':
And here's UITableViewController implementation:
class ViewController: UITableViewController {
}
class TableCell: UITableViewCell {
}
class CollectionCell: UICollectionViewCell {
}
extension TableCell: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath)
return cell
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
}
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 :)
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()
}
My UICollectionView has a UILabel and a UIImageView, i figure it them and works well like this:
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("coffee_brand_cell", forIndexPath: indexPath) //as! AURCoffeeBrandCollectionViewCell
let imageView = cell.contentView.viewWithTag(1) as? UIImageView
imageView?.image = UIImage(named: ["coffee1","coffee2","coffee3","coffee3"][indexPath.row])
let name = cell.contentView.viewWithTag(2) as? UILabel
name?.text = coffeeName[indexPath.row] + String(indexPath.row)
name?.textColor = UIColor(red: 226.0/255.0, green: 170.0/255.0, blue: 119.0/255.0, alpha: 1.0)
name?.adjustsFontSizeToFitWidth = true
cell.backgroundColor = collectionView.backgroundColor
cell.layoutIfNeeded()
imageView?.layer.cornerRadius = (cell.frame.width - 40)/2.0
imageView?.layer.masksToBounds = true
return cell
}
But i can't get the selected cell's name and image like below,
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let cell = collectionView.cellForItemAtIndexPath(indexPath)
if let name = cell?.contentView.viewWithTag(2) {
//Can't get into this.
}
}
}
and cell's contentView subviews return 0.
cell!.contentView.subviews
0 elements
Update:
cell.contentView.viewWithTag(2) works in cellForItemAtIndexPath, but not in didSelectItemAtIndexPath. however cell.viewWithTag(2) works.
Why contentViewworks different?
update
Insert this two lines into didSelectItemAtIndexPath
print(" selected cell is \((cell?.viewWithTag(2) as! UILabel).text!)")
print(" selected cell is \((cell?.contentView.viewWithTag(2) as! UILabel).text!)")
output:
selected cell is Kii Kenya0
fatal error: unexpectedly found nil while unwrapping an Optional value
Project can be download here: Link
PS: I checked the 'Installed' for the contentView's subViews.
CollectionView in simulator.
Try using this
import UIKit
class CollectionUIViewController: UIViewController,UICollectionViewDataSource,UICollectionViewDelegate{
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return 20
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("customCellIdentifier", forIndexPath: indexPath)
(cell.contentView.viewWithTag(1) as! UIImageView).image = UIImage(named: "Image")
(cell.contentView.viewWithTag(2) as! UILabel).text = "cell no \(indexPath.row)"
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
let selectedCell = collectionView.cellForItemAtIndexPath(indexPath)
print(" selected cell is \((selectedCell?.contentView.viewWithTag(2) as! UILabel).text!)")
}
}
I get the selected cell's label text by accessing it using viewWithTag (attached snapshot for reference)
I'm easily able to change the background color of a cell in the CellForItemAtIndexPath method
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
cell.backgroundColor = UIColor.blackColor()
}
However, when I attempt to change the color in the DidSelectItemAtIndexPath it does not work.
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
let cell: ButtonCollectionCell = collectionView.dequeueReusableCellWithReuseIdentifier("ButtonCell", forIndexPath: indexPath) as! ButtonCollectionCell {
cell.backgroundColor = UIColor.blackColor()
}
Also I read somewhere that using didSelectItemAtIndexPath won't work because once the collection view begins scrolling the color will change back
What is the fix in Swift?
Thank you so much for your help
You can use this method for that:
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath){
var cell : UICollectionViewCell = collectionView.cellForItemAtIndexPath(indexPath)!
cell.backgroundColor = UIColor.magentaColor()
}
Old question, but it can help someone:
You can't simply modify the cell, since your changes will be lost when you scroll your UICollectionView, or even worst, other cells could appear with a wrong background, because they'll be reused.
So, the best way to do that is create an array of NSIndexPath and append your selected indexPaths:
var selectedIndexes = [NSIndexPath]() {
didSet {
collectionView.reloadData()
}
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath){
// ...
if let indexSelecionado = selectedIndexes.indexOf(indexPath) {
selectedIndexes.removeAtIndex(indexSelecionado)
} else {
selectedIndexes.append(indexPath)
}
}
// ...
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
// ...
if self.selectedIndexes.indexOf(indexPath) == nil {
cell.backgroundColor = UIColor.whiteColor() // Unselected
} else {
cell.backgroundColor = UIColor.redColor() // Selected
}
return cell
}
You can override UICollectionViewCell isSelected . It will apply changes in selected method.
class ButtonCollectionCell: UICollectionViewCell {
override var isSelected: Bool{
didSet{
if self.isSelected
{
self.layer.backgroundColor = colorLiteral(red: 0.8058760762, green: 0.2736578584, blue: 0.1300437152, alpha: 1)
} else
{
self.layer.backgroundColor = colorLiteral(red: 0, green: 0, blue: 0, alpha: 0)
}
}
}
}
cell.backgroundColor = UIColor.redColor()
let startTime = DateUtils.getDispatchTimeByDate(NSDate(timeIntervalSinceNow: 0.1))
dispatch_after(startTime, dispatch_get_main_queue()) {[weak self] in
//there is the code redirect to other viewcontroller
openOtherVC()
}