集合视图单元格中正常状态的 UIButton 图像每四个单元格重复一次 [英] UIButton image for normal state in collectionview cell repeats itself every four cells

查看:14
本文介绍了集合视图单元格中正常状态的 UIButton 图像每四个单元格重复一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试为位于 collectionView 单元格中的按钮的正常状态设置图像.按下按钮时,图像会发生变化.问题是每四个单元格在按下按钮时重复与原始单元格相同的图像.有没有办法让它不重复,当按下按钮时,它只针对那个单独的单元格?

I'm trying to set an image for a button's normal state which is located in a collectionView cell. When the button is pressed the image changes. The problem is every four cells it repeats the same image as the original cell when the button is pressed. Is there a way to not have it repeat itself and when the button is pressed its only for that individual cell?

代码如下:

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))

    }
}

我试过这样做,但出于某种奇怪的原因,即使按下按钮,已选择"状态图像也不会显示:

I've tried doing this but for some strange reason the 'selected' state image is never shown even when the button is pressed:

let button = UIButton()

override func awakeFromNib() {
    super.awakeFromNib()

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

推荐答案

每次你的单元格 dequeued cellForItemAt 都会被调用.这是您配置单元数据的地方.因此,如果您需要显示标记为收藏的单元格,可以在此处进行.

Every time your cell is dequeued cellForItemAt is called. This is the place where you configure your cell data. So if you need to show cell marked as favourite, you can do it here.

那么你是怎么做到的呢?假设您的所有单元格一开始都没有被选中.美好的.您不必在 cellForItemAt 中说任何内容.现在假设您将一些单元格标记为收藏.这里发生的情况是,当单元格可见时,它将反映更改,因为按钮已连接到将进行更改的选择器.

So how do you do it there? Let's say all your cells are not selected in the beginning. Fine. You don't have to say anything in cellForItemAt. Now let's say you mark a few cells as favourite. What happens here is, it will reflect the change when the cell is visible because the button is hooked to a selector which will make the changes.

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

Now here is the problem. When you scroll and the cell disappears, the information about your cell being marked as favourite is lost! So what you need to do, is maintain an array which will store the IndexPath of all the selected cells. (Make sure to remove the IndexPath when a cell is removed from favourite!) Let's call that array favourites. If you can use your data source for the collection view to store the selected state information that is also fine. Now you have to store the information about whether your cell is marked as favourite in your button selector.

@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.如果是,则调用将单元格设置为选定状态的方法.

After you have stored the information about the cell, every time you dequeue a cell, you need to check if the IndexPath is favourites. If it is, you call a method which sets the cell in the selected state.

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

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

Done? No! Now we have another problem. This problem is associated with the reuse of the cell. So what happens in cellForItemAt actually? You dequeue a cell and use it to display information. So when you dequeue it what happens is, it might have already been used for showing some other information in some other index path. So all the data that was existing there will persist. (Which is why you have the problem of favourites repeating every 4 cells!)

那么我们该如何解决呢?UICollectionViewCell 中有一个方法被称为 before 单元格出列 - prepareCellForReuse.您需要在您的单元格中实现此方法并从单元格中删除所有信息,以便它到达 cellForItemAt 时是新鲜的.

So how do we solve this? There is method in UICollectionViewCell which is called before a cell is dequeued - prepareCellForReuse. You need to implement this method in your cell and remove all the information from the cell, so that it is fresh when it arrives at cellForItemAt.

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

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

Or you could always set every value of everything inside the cell in cellForItemAt so that every information is always overwritten with the necessary value.

OP 说他在集合视图中有一个集合视图.你可以像这样识别哪个集合视图被调用,

OP says he has a collection view inside a collection view. You can identify which collection view is called like this,

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
}

这篇关于集合视图单元格中正常状态的 UIButton 图像每四个单元格重复一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆