一尘不染

CollectionView单元格中处于正常状态的UIButton图像每四个单元格重复一次

swift

我正在尝试为位于collectionView单元中的按钮的正常状态设置图像。当按下按钮时,图像改变。问题在于,每四个单元格在按下按钮时会重复与原始单元格相同的图像。有没有办法让它自己重复一次?当按下按钮时,它仅适用于该单个单元格吗?

这是代码:

class FavoritesCell: UICollectionViewCell {

  var isFavorite: Bool = false

  @IBOutlet weak var favoritesButton: UIButton!

  @IBAction func favoritesButtonPressed(_ sender: UIButton) {
        _ = self.isFavorite ? (self.isFavorite = false, self.favoritesButton.setImage(UIImage(named: "favUnselected"), for: .normal)) : (self.isFavorite = true, self.favoritesButton.setImage(UIImage(named: "favSelected"), for: .selected))

    }
}

我尝试这样做,但由于某些奇怪的原因,即使按下按钮,也不会显示“选定”状态图像:

let button = UIButton()

override func awakeFromNib() {
    super.awakeFromNib()

    button.setImage(UIImage(named: "favUnselected"), for: .normal)
    button.setImage(UIImage(named: "favSelected"), for: .selected)
}

阅读 216

收藏
2020-07-07

共1个答案

一尘不染

每次您的单元 出队时 cellForItemAt都会调用。在此配置单元数据。因此,如果需要显示标记为收藏夹的单元格,则可以在此处进行。

那么,你在那里怎么做?假设您一开始没有选择所有单元格。精细。您不必在中说什么cellForItemAt。现在,假设您将几个单元格标记为收藏。这里发生的是,当单元格可见时,它将反映更改,因为按钮已钩到将进行更改的选择器上。

现在这是问题所在。当您 滚动
并且该单元格消失时,关于您的单元格被标记为收藏夹的信息将会丢失!因此,您需要做的是维护一个数组,该数组将存储IndexPath所有选定单元格的。(确保IndexPath从收藏夹中删除单元格时删除!)我们将该数组称为favourites。如果您可以将数据源用于收集视图来存储选定的状态信息,那也很好。现在,您必须在按钮选择器中存储有关您的单元是否被标记为收藏夹的信息。

@objc func buttonTapped() {
    if favourites.contains(indexPath) {   // Assuming you store indexPath in cell or get it from superview
        favourites.removeAll(where: {$0 == indexPath})
    } else {
        favourites.append(indexPath)
    }
}

存储有关单元格的信息后,每次使单元格出队时,都需要检查IndexPathis
是否为favourites。如果是,则调用将单元格设置为选定状态的方法。

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    // Dequeue cell and populating cell with data, etc
    if favourites.contains(indexPath) {
        cell.showFavourite()
    }
}

做完了吗 没有!现在我们还有另一个问题。此问题与单元的 重用 有关。那么cellForItemAt实际上发生了什么?您使单元 出队
并使用它显示信息。因此,当您将其出队时,所发生的是,它可能已被用于在其他索引路径中显示其他信息。因此,在那里 存在的 所有数据都将 保留
。(这就是为什么您的收藏夹每4个单元重复一次的问题!)

那么我们该如何解决呢?在单元出队 之前, 有一种方法UICollectionViewCell被调用-
。您需要在单元格中实现此方法,并从单元格中删除所有信息,以使它到达时是新鲜的。 __prepareCellForReuse``cellForItemAt

func prepareForReuse() {
     //Remove label text, images, button selected state, etc
}

或者,您可以始终在其中设置单元格中所有内容的每个值,cellForItemAt以便始终用必要的值覆盖每个信息。

编辑:OP说他在集合视图中有一个集合视图。您可以确定这样调用哪个集合视图,

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    if collectionView === favoriteCollectionView { // This is the collection view which contains the cell which needs to be marked as favourite
        // Dequeue cell and populating cell with data, etc
        if favourites.contains(indexPath) {
            cell.showFavourite()
        }
        return cell
    }
    // Dequeue and return for the other collectionview
}
2020-07-07