I'm working on collectionView and stuck on like when user tap on collectionView cell item it change the colour accordingly and other item colour also change.First cell item would be active and colour will be blue and other cell colour will be deactive and colour gray.But in my case the code not working fine see code below.
var category: [Category] = [
Category(cat: "For You"),
Category(cat: "Top chats"),
Category(cat: "Kids"),
Category(cat: "Categories"),
Category(cat: "Editor Choice")
]
var isSelected: Int? = nil {
didSet {
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}
}
extension DashboardViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.isSelected = indexPath.row
}
}
extension DashboardViewController: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return category.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
configureDashboardCell(collectionView, cellForItemAt: indexPath)
}
func configureDashboardCell(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: CategoryCell.self), for: indexPath) as? CategoryCell else {return UICollectionViewCell()}
cell.lblName.text = category[indexPath.item].cat
if self.isSelected == indexPath.row {
let textColor: UIColor = .blue
let underLineColor: UIColor = .blue
let underLineStyle = NSUnderlineStyle.single.rawValue
let labelAtributes:[NSMutableAttributedString.Key : Any] = [
NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.underlineStyle: underLineStyle,
NSAttributedString.Key.underlineColor: underLineColor
]
let underlineAttributedString = NSAttributedString(string: cell.lblName.text ?? "",
attributes: labelAtributes)
cell.lblName.attributedText = underlineAttributedString
} else {
let textColor: UIColor = .gray
let labelAtributes:[NSMutableAttributedString.Key : Any] = [
NSAttributedString.Key.foregroundColor: textColor
]
let underlineAttributedString = NSAttributedString(string: cell.lblName.text ?? "",
attributes: labelAtributes)
cell.lblName.attributedText = underlineAttributedString
}
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: (self.collectionView.bounds.width / 3) - 5 , height: 40)
}
}
CodePudding user response:
In my opinion, I would recomment you isSelected
property to control all of the style.
// Cells become highlighted when the user touches them.
// The selected state is toggled when the user lifts up from a highlighted cell.
// Override these methods to provide custom UI for a selected or highlighted state.
// The collection view may call the setters inside an animation block.
open var isSelected: Bool
You should put all the task to cell, rather than directly control it through collectionView.
As you mentioned above,
First cell item would be active and colour will be blue and other cell colour will be deactive and colour gray
so you just want two State, either selected
or deselected
, and one selected only.
Let we have a try
collection.selectItem(at: <#T##IndexPath?#>, animated: <#T##Bool#>, scrollPosition: <#T##UICollectionView.ScrollPosition#>)
, it make cell call isSelected
twice both for new selected Cell and the old one needed to deselect.
CodePudding user response:
Please use your selection in willDisplayCell
. First let the cell to be in the view in cellForRowAt
and then try to redesign the cell whatever you wish.
func configureDashboardCell(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: CategoryCell.self), for: indexPath) as? CategoryCell else {return UICollectionViewCell()}
cell.lblName.text = category[indexPath.item].cat
let textColor: UIColor = .gray
let labelAtributes:[NSMutableAttributedString.Key : Any] = [
NSAttributedString.Key.foregroundColor: textColor
]
let underlineAttributedString = NSAttributedString(string: cell.lblName.text ?? "",
attributes: labelAtributes)
cell.lblName.attributedText = underlineAttributedString
return cell
}
func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
if self.isSelected == indexPath.row {
let textColor: UIColor = .blue
let underLineColor: UIColor = .blue
let underLineStyle = NSUnderlineStyle.single.rawValue
let labelAtributes:[NSMutableAttributedString.Key : Any] = [
NSAttributedString.Key.foregroundColor: textColor,
NSAttributedString.Key.underlineStyle: underLineStyle,
NSAttributedString.Key.underlineColor: underLineColor
]
let underlineAttributedString = NSAttributedString(string: cell.lblName.text ?? "",
attributes: labelAtributes)
cell.lblName.attributedText = underlineAttributedString
}
}
and reload data when the cell is tapped
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
self.isSelected = indexPath.row
collectionView.reloadData()
}