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

时间:2018-08-30 15:42:30

标签: ios swift uicollectionview uicollectionviewcell

我正在尝试为位于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)
}

2 个答案:

答案 0 :(得分:0)

该单元格最有可能被重用,并且您的isFavorite设置为true

只需尝试添加

func prepareForReuse() {
    super.prepareForReuse()
    self.isFavorite = false
}

当要重复使用单元格时,此按钮会将按钮设置为原始图像。

另外,由于您的按钮有两种状态,selected为什么会跳舞

  _ = self.isFavorite ? (self.isFavorite = false, self.favoritesButton.setImage(UIImage(named: "favUnselected"), for: .normal)) : (self.isFavorite = true, self.favoritesButton.setImage(UIImage(named: "favSelected"), for: .selected))

您只能说self.favoritesButton.selected = self.isFavorite

将您的手机代码更改为:

class FavoritesCell: UICollectionViewCell {
    @IBOutlet weak var favoritesButton: UIButton!

    var isFavorite: Bool = false {
        didSet {
            favoritesButton.selected = isFavorite
        }
    }

    @IBAction func favoritesButtonPressed(_ sender: UIButton) {
        favoritesButton.selected = !favoritesButton.selected       
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        isFavorite = false
    }
}

答案 1 :(得分:0)

您的单元格每次出队 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)
    }
}

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

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

完成了吗?没有!现在我们还有另一个问题。此问题与单元格的重用有关。那么cellForItemAt中会发生什么呢?您出队一个单元格并使用它来显示信息。因此,当您使它出队时,所发生的是,它可能已经用于在其他索引路径中显示其他信息。因此,在那里存在的所有数据都会 persist 。 (这就是为什么您的收藏夹每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
}