UICollectionView 重用单元格背景问题

Posted

技术标签:

【中文标题】UICollectionView 重用单元格背景问题【英文标题】:UICollectionView reuse cell background issue 【发布时间】:2017-06-29 07:53:41 【问题描述】:

我正在使用 UICollectionview 呈现 4 个按钮,用户应该选择 1 个按钮。 我创建了 uibutton 的自定义子类

class CustomButton: UIButton 

    override var isSelected: Bool
        didSet
            backgroundColor =  isSelected ? Constants.Colors.selectedMenu: Constants.Colors.menuCell
        
    


自定义单元格类:

class SymptomCell: UICollectionViewCell 

    @IBOutlet weak var optionButton1: UIButton!
    @IBOutlet weak var optionButton2: UIButton!
    @IBOutlet weak var optionButton3: UIButton!
    @IBOutlet weak var optionButton4: UIButton!


    func configCell(options :  [String])
        optionButton1.setTitle(options[0], for: .normal)
        optionButton2.setTitle(options[1], for: .normal)
        optionButton3.setTitle(options[2], for: .normal)
        optionButton4.setTitle(options[3], for: .normal)
    

    @IBAction func clickAction(_ sender: UIButton) 
         sender.isSelected = sender.isSelected ? false : true
    

我看到,例如,如果我选择按钮并再滚动几个单元格,那么即使我没有按下它,同一索引中的按钮也会获得不同的背景颜色。

在我尝试使用的单元类中:

 override func prepareForReuse() 
        optionButton1.isSelected = false
        optionButton2.isSelected = false
       // ...
 

但它每次都会取消选择所有项目。 我该怎么办?

【问题讨论】:

你确定它会取消全选吗? @LeangSocheat 它会在我滑动到下一个单元格时取消选择所有按钮 你的 gif 看起来像页面视图控制器或滚动视图..lolz。 你可以用这个推送你的保留代码吗? @LeangSocheat 请立即查看 【参考方案1】:

UICollectionViewCell 内的任何 UIView 在单元重用之间必须是无状态的,因此,您必须保留您的 prepareForReuse 函数。

但是,UICollectionViewCell 本身正在恢复其 isSelected 状态,当它在之前选择的 indexPath 处重复使用时。

因此,方法可以是选择单元格和按钮。 在你的牢房里应该有这样的东西:

protocol MyCellDelegate : NSObjectProtocol 
    func optionButton1DidToggle(in cell: UICollectionViewCell?)


class MyCell: UICollectionViewCell 

    var delegate : MyCellDelegate?

    @IBAction func clickAction(_ sender: UIButton) 
        // you can assign delegate to your cell, the same as UICollectionViewDelegate, and forward here click callback to your delegate,
        delegate?.optionButton1DidToggle(in: self) 
        //.....
    

    override var isSelected: Bool 
        didSet
            optionButton1.isSelected = self.isSelected
        
    

    override func prepareForReuse() 
        optionButton1.isSelected = false
    

MyCellDelegate 实现:

public func optionButton1DidToggle(in cell: UICollectionViewCell?) 
    if !cell.optionButton1.isSelected 
        collectionView.selectItem(at: collectionView.indexPath(for: cell) animated:false scrollPosition:.centeredHorizontally)
     else 
        collectionView.deselectItem(at: collectionView.indexPath(for: cell) animated:false)
    

【讨论】:

如果我只有 1 个“optionButton”怎么办? 你的意思是一个单元格中有多个按钮?然后你需要一个模型在你的UICollectionViewDataSource 后面,每个模型对象将存储每个indexPath 的单元格按钮的状态。您将在UICollectionViewDataSource collectionView(_ cellForItemAt: indexPath) 函数中将状态设置为按钮。【参考方案2】:

尝试在您的自定义单元格中使用 prepareForReuse 并设置 backgroundColor = nil

override func prepareForReuse() 

    backgroundColor =  nil
    optionButton1.isSelected = false

【讨论】:

以上是关于UICollectionView 重用单元格背景问题的主要内容,如果未能解决你的问题,请参考以下文章

重用单元格 UICollectionView - 某些单元格没有被选中

UICollectionView 不重用单元格

UICollectionView 重用单元格问题

拖放 UICollectionView 单元格重用问题

在 UICollectionView 上禁用单元格重用

如何不在 UICollectionView 中重用单元格 - Swift