>我正在尝试为位于 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)
}
每次您的小区取消排队时,都会被调用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
到底发生了什么呢?您可以取消单元格的排队并使用它来显示信息。因此,当您取消排队时,发生的情况是,它可能已经用于在其他索引路径中显示一些其他信息。因此,那里存在的所有数据都将保留下来。(这就是为什么您有收藏夹每 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
}
该单元格很可能被重复使用,并且您的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
}
}