Reputation: 3221
I have a UICollectionView, and the user is able to select multiple cells. It's a bit difficult to keep track of which cells have been selected, so I need some way to go about highlighting/creating a border when the cell is tapped.
Code:
func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool {
addToList.append(objectsArray[indexPath.row])
return true
}
Upvotes: 29
Views: 73976
Reputation: 674
SWIFT
Add this code to your UICollectionViewCell subclass:
override var isSelected: Bool {
didSet{
if self.isSelected {
UIView.animate(withDuration: 0.3) { // for animation effect
self.backgroundColor = UIColor(red: 115/255, green: 190/255, blue: 170/255, alpha: 1.0)
}
}
else {
UIView.animate(withDuration: 0.3) { // for animation effect
self.backgroundColor = UIColor(red: 60/255, green: 63/255, blue: 73/255, alpha: 1.0)
}
}
}
}
This will set the color of a single selected cell, and remove the selected color from any previous selected cells. I've added a smooth animation to it. I think it's nice, but it's optional.
Upvotes: 22
Reputation: 1
With ternary operator
override var isSelected: Bool {
didSet {
UIView.animate(withDuration: 0.3) {
self.backgroundColor = self.isSelected ? .systemGray4 : .systemGray6
}
}
}
Upvotes: 0
Reputation: 33
Try this code to highlight collection view cell
func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) {
cell.contentView.backgroundColor = #colorLiteral(red: 1, green: 0.4932718873, blue: 0.4739984274, alpha: 1)
}
}
func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {
if let cell = collectionView.cellForItem(at: indexPath) {
cell.contentView.backgroundColor = nil
}
}
Upvotes: 1
Reputation: 5202
Here is my solution, and I'm sure it works.
My solution includes 3 highlight effects, UICollectionCell
's selectedBackgroundView
, cell.contentView.backgroundColor
, or your your own specialHighlightedArea
; just feel free to choose the one you need, and feel free to add more effects as your App's Designer requires.
How to use? Just inherit BaseCollectionViewCell
. If needed, configure in cell's init
or collectionView
's delegate methods.
If you don't need highlight effect, just find a method named 'shouldHighlightItemAtIndexPath' in UICollectionViewDelegate and return false
or just set cell.shouldTintBackgroundWhenSelected = false
.
extension UIColor {
convenience init(rgb: Int, alpha: CGFloat = 1.0) {
self.init(red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0, green: CGFloat((rgb & 0xFF00) >> 8) / 255.0, blue: CGFloat(rgb & 0xFF) / 255.0, alpha: alpha)
}
}
/// same with UITableViewCell's selected backgroundColor
private let cellHighlightedColor = UIColor(rgb: 0xD8D8D8)
class BaseCollectionViewCell: UICollectionViewCell {
var shouldTintBackgroundWhenSelected = true // You can change default value
var specialHighlightedArea: UIView?
// make lightgray background show immediately(on touch)
// (使灰背景在手指触到 cell 时立即出现)
override var isHighlighted: Bool {
willSet {
onSelected(newValue)
}
}
// keep lightGray background from selected until unselected
// (保留灰背景直至取消选中)
override var isSelected: Bool {
willSet {
onSelected(newValue)
}
}
func onSelected(_ newValue: Bool) {
// selectedBackgroundView is defined by UICollectionViewCell
guard selectedBackgroundView == nil else { return }
if shouldTintBackgroundWhenSelected {
contentView.backgroundColor = newValue ? cellHighlightedColor : UIColor.clear
}
if let sa = specialHighlightedArea {
sa.backgroundColor = newValue ? UIColor.black.withAlphaComponent(0.4) : UIColor.clear
}
}
}
Upvotes: 18
Reputation: 7129
For multiple selection of cell, you can do it as follow:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath){
if let currentCell = collectionView.cellForItem(at: indexPath) as? QuestionnaireCollectionViewCell {
// Your selection logic, you can change it according to your requirement
if currentCell.selectedImage.isHidden == true{
currentCell.selectedImage.isHidden = false
}
else{
currentCell.selectedImage.isHidden = true
}
}
}
}
For single selection you can use isSelected in your collectionviewcell class as follow:
override var isSelected: Bool{
didSet{
if self.isSelected
{
//This block will be executed whenever the cell’s selection state is set to true (i.e For the selected cell)
}
else
{
//This block will be executed whenever the cell’s selection state is set to false (i.e For the rest of the cells)
}
}
}
Upvotes: 4
Reputation: 1979
You can create a customized collcetionViewCell, and override:
class MyCell: UICollectionViewCell {
override var isHighlighted: Bool {
didSet {
if self.isHighlighted {
print("yes")
// Your customized animation or add a overlay view
} else {
print("no")
// Your customized animation or remove overlay view
}
}
}
}
This way, you can create similar result like the highlight effect on UITableViewCell.
Without subclassing:
If you don't want to create your own collectionViewCell. you can use the delegate method:
func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath)
func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath)
You can do the same thing with it.
Upvotes: 6
Reputation: 109
Try to make the borders thick enough to cover the entire cell
Code:
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
addToList.append(objectsArray[indexPath.row])
let cell = collectionView.cellForItem(at: indexPath)
cell?.layer.borderWidth = 200.0
cell?.layer.borderColor = UIColor.init(red: 0/255, green: 0/255, blue: 0/255, alpha: 0.4).cgColor
}
Upvotes: 0
Reputation: 7013
you can use border change on didSelectItemAtIndexPath
override event like the below code and assign new settings on the cell.
Swift 3.x:
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
addToList.append(objectsArray[indexPath.row])
let cell = collectionView.cellForItem(at: indexPath)
cell?.layer.borderWidth = 2.0
cell?.layer.borderColor = UIColor.gray.cgColor
}
Upvotes: 53
Reputation: 9590
Use
collectionView.reloadItemsAtIndexPaths([indexPath])
to reload current cell, or
collectionView.reloadData()
to reload all cells in shouldSelectItemAtIndexPath
Then in cellForItemAtIndexPath
set your border or background color if the cell is marked as checked (you may need a new array for checked cells with preferably indexPaths.
Upvotes: 6