Изображение UIButton для нормального состояния в ячейке коллекции повторяется каждые четыре ячейки - PullRequest
0 голосов
/ 30 августа 2018

Я пытаюсь установить изображение для нормального состояния кнопки, которое находится в ячейке 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 голосов
/ 30 августа 2018

Каждый раз, когда ваша клетка вызывается, вызывается 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
}
0 голосов
/ 30 августа 2018

Ячейка, скорее всего, используется повторно, а для 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
    }
}
...