我已经实现了一个UICollectionViewController的子类,它可以水平滚动,我希望它能够只选择一个项目。
当我在当前屏幕上更改所选项目时,它工作正常。但是,例如,如果我在集合的最开头选择一个项目,然后向右滚动并选择另一个项目,则仍然会选择第一个项目。
这是我的CollectionView的当前版本:
class GenresCollectionVC: UICollectionViewController {
var selectedIndexPath: IndexPath?
// MARK: UICollectionViewDataSource
override func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return MockData.instance.genres.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(
withReuseIdentifier: reuseIdentifier, for: indexPath) as! GenreCollectionViewCell
cell.genreNameLabel.text = MockData.instance.genres[indexPath.row]
if selectedIndexPath == indexPath {
redraw(selectedCell: cell)
} else {
redraw(deselectedCell: cell)
}
return cell
}
// MARK: UICollectionViewDelegate
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) as? GenreCollectionViewCell else {
return
}
redraw(selectedCell: cell)
selectedIndexPath = indexPath
}
override func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) as? GenreCollectionViewCell else {
return
}
redraw(deselectedCell: cell)
selectedIndexPath = nil
}
private func redraw(selectedCell cell: GenreCollectionViewCell
) {
cell.layer.borderWidth = 1.0
cell.layer.cornerRadius = cell.bounds.height / 2
cell.layer.borderColor = UIColor.violetNeeoColor.cgColor
cell.genreNameLabel.textColor = UIColor.violetNeeoColor
}
private func redraw(deselectedCell cell: GenreCollectionViewCell) {
cell.layer.borderWidth = 0.0
cell.layer.cornerRadius = 0.0
cell.genreNameLabel.textColor = UIColor.white
}
}
我做错了什么?
答案 0 :(得分:6)
在GenreCollectionViewCell
课程中,覆盖isSelected
属性,即
override var isSelected: Bool{
willSet{
super.isSelected = newValue
if newValue
{
self.layer.borderWidth = 1.0
self.layer.cornerRadius = self.bounds.height / 2
self.layer.borderColor = UIColor.violetNeeoColor.cgColor
self.genreNameLabel.textColor = UIColor.violetNeeoColor
}
else
{
self.layer.borderWidth = 0.0
self.layer.cornerRadius = 0.0
self.genreNameLabel.textColor = UIColor.white
}
}
}
现在,您无需在didSelectItemAt
delegate
方法中手动选择/取消选择该单元格。 isSelected
属性会自动处理它。
答案 1 :(得分:2)
在这种情况下,保存IndexPath
然后使用它作为比较的基础对我来说总是最好的选择。
首先定义你的变量:
var _selectedIndexPath : IndexPath? = nil
然后在didSelectItemAtIndexPath
:
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath){
if ((_selectedIndexPath) != nil){
if indexPath.compare(_selectedIndexPath!) == ComparisonResult.orderedSame {
//if the user tap the same cell that was selected previously deselect it.
_selectedIndexPath = nil;
}
else
{
\ // save the currently selected indexPath
_selectedIndexPath = indexPath
}
}
else{
// else, savee the indexpath for future reference if we don't have previous selected cell
_selectedIndexPath = indexPath;
}
// and now only reload only the visible cells
collectionView.reloadItems(at: collectionView.indexPathsForVisibleItems)
}
最后检查cellForItemAtIndexPath
中选定的单元格:
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
// Demo implementation
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath as IndexPath)
if _selectedIndexPath == indexPath{
//If the cell is selected
cell.isSelected = true
cell.backgroundColor = UIColor.red
}
else{
// If the cell is not selected
cell.isSelected=false
cell.backgroundColor = UIColor.gray
}
return cell
}
答案 2 :(得分:1)
选择新的indexPath
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
guard let cell = collectionView.cellForItem(at: indexPath) as? GenreCollectionViewCell else {
return
}
if selectedIndexPath != indexPath {
collectionView(collectionView, didDeselectItemAt: selectedIndexPath)
}
redraw(selectedCell: cell)
selectedIndexPath = indexPath
}
显然,每隔一次点击一个单元格就会调用取消选择委托方法。