web-dev-qa-db-fra.com

Changer le fond de la cellule UICollectionView au robinet

J'ai un UICollectionView que j'ai créé par programme. J'aimerais que la vue de collection se comporte de la manière suivante:

1. User touches cell
2. Cell background color changes
3. User releases touch
4. Cell background color changes

Cela devrait être un changement de couleur rapide qui se produit juste avant que le sélecteur lié à l'action tap soit exécuté, dans lequel le contrôleur de vue contenant la vue de collection est extrait de la pile.

Je suis en train de regarder cette question: UICollectionView fond de changement de cellule en tapant

dans lequel figure le résumé suivant des méthodes à utiliser à cette fin:

// Methods for notification of selection/deselection and highlight/unhighlight events.
// The sequence of calls leading to selection from a user touch is:
//
// (when the touch begins)
// 1. -collectionView:shouldHighlightItemAtIndexPath:
// 2. -collectionView:didHighlightItemAtIndexPath:
//
// (when the touch lifts)
// 3. -collectionView:shouldSelectItemAtIndexPath: or -    collectionView:shouldDeselectItemAtIndexPath:
// 4. -collectionView:didSelectItemAtIndexPath: or -collectionView:didDeselectItemAtIndexPath:
// 5. -collectionView:didUnhighlightItemAtIndexPath:

Je suppose que je n'ai besoin que de mettre en œuvre l'une des méthodes ci-dessus à partir de «quand le toucher commence» et «quand le toucher se termine». Mais peu importe ce que je fais, il semble qu'une couleur d'arrière-plan change puis reste changée. Voici un exemple de quelque chose que j'ai tenté mais qui n'a pas fonctionné:

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
 {
   //pop vc 
 }

- (void)collectionView:(UICollectionView *)collectionView didHighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
  UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
  cell.contentView.backgroundColor = [UIColor redColor];
}

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
  UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
  cell.contentView.backgroundColor = [UIColor greenColor];
}

Il en résulte que la couleur d'arrière-plan de la cellule est uniquement changée en rouge. J'ai également examiné cette question: Problème de sélection et de désélection de UICollectionView et essayé d'implémenter [UICollectionView selectItemAtIndexPath: animé: scrollPosition:] et de l'appeler dans didSelectItemAtIndexPath, mais cela ne fonctionnait pas non plus. La source de données et le délégué de la vue Collection sont définis.

27
jac300

Le problème est que vous changez la couleur sur mettez en surbrillance et la remettez sur désélectionnez au lieu de cela sur unhighlight

Vous devriez simplement changer ceci:

- (void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath
{
  UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
  cell.contentView.backgroundColor = [UIColor greenColor];
}

pour ça:

- (void)collectionView:(UICollectionView *)collectionView didUnhighlightItemAtIndexPath:(NSIndexPath *)indexPath
{
  UICollectionViewCell *cell = [collectionView cellForItemAtIndexPath:indexPath];
  cell.contentView.backgroundColor = [UIColor greenColor];
}

De plus, si vous ne voulez pas attendre un peu avant que votre surbrillance ne se produise, vous devez définir la propriété delaysContentTouches de la vue de collection sur NO.

Edit: assurez-vous également que vous appelez 

[collectionView deselectItemAtIndexPath:indexPath animated:NO];

dans la méthode -didSelectItemAtIndexPath

45
Antonio E.

Version Swift 3

Ajoutez les deux méthodes suivantes à votre classe de contrôleur de vue:

// change background color when user touches cell
func collectionView(_ collectionView: UICollectionView, didHighlightItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath)
    cell?.backgroundColor = UIColor.red
}

// change background color back when user releases touch
func collectionView(_ collectionView: UICollectionView, didUnhighlightItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath)
    cell?.backgroundColor = UIColor.green
}

Voir ici pour obtenir de l'aide pour configurer une vue de collection de base dans Swift.

29
Suragch

Edit: Réponse dans Swift 3

var selectedIndex = Int ()

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! CollectionViewCell

    cell.backgroundColor = selectedIndex == indexPath.row ? UIColor.green : UIColor.red

    return cell
}

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
    selectedIndex = indexPath.row

    self.yourCollctionView.reloadData()
}
5
Abirami Bala

Voici ma solution. Et je suis sûr que ça marche vraiment.
Je propose trois méthodes pour mettre en évidence une cellule (selectedBackgroundView, teinter cell.contentView et teinter une zone spéciale). 

Comment utiliser:
1. héritez simplement BaseCollectionViewCell et ne faites rien;
2. hériter et définir specialHighlightedArea = UIView(), et contentView.addSubView(specialHighlightedArea), puis le mettre en forme ou ajouter une contrainte pour utiliser la mise en page automatique;
3. si vous n'avez pas besoin d'effet de surbrillance, écrivez simplement une méthode nommée 'shouldHighlightItemAtIndexPath' définie par UICollectionViewDelegate et rendez-la à false, ou définissez cell.shouldTintBackgroundWhenSelected = false et définissez specialHighlightedArea = nil et supprimez-la de superView.

/// same with UITableViewCell's selected backgroundColor
private let highlightedColor = UIColor(rgb: 0xD8D8D8) 

/// you can make all your collectionViewCell inherit BaseCollectionViewCell
class BaseCollectionViewCell: UICollectionViewCell {

    /// change it as you wish when or after initializing
    var shouldTintBackgroundWhenSelected = true

    /// you can give a special view when selected
    var specialHighlightedArea: UIView? 

    // make lightgray background display immediately(使灰背景立即出现)
    override var isHighlighted: Bool { 
        willSet {
            onSelected(newValue)
        }
    }

    // keep lightGray background until unselected (保留灰背景)
    override var isSelected: Bool { 
        willSet {
            onSelected(newValue)
        }
    }

    func onSelected(_ newValue: Bool) {
        guard selectedBackgroundView == nil else { return }
        if shouldTintBackgroundWhenSelected {
            contentView.backgroundColor = newValue ? highlightedColor : UIColor.clear
        }
        if let area = specialHighlightedArea {
            area.backgroundColor = newValue ? UIColor.black.withAlphaComponent(0.4) : UIColor.clear
        }
    }
}

extension UIColor {
    convenience init(rgb: Int, alpha: CGFloat = 1.0) {
        self.init(red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0, green: CGFloat((rgb & 0xFF00) >> 8) / 255.0, blue: CGFloat(rgb & 0xFF) / 255.0, alpha: alpha)
    }
}
4
DawnSong

Solution de logique binaire simple. Fonctionne avec Swift 3 et 4:

func collectionView(_ collectionView: UICollectionView, didSelectItemAt
    indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath) as! CategoryCell
    let lastCellColor = cell.backgroundColor
    if cell.isSelected {cell.backgroundColor = .green} else {cell.backgroundColor = lastCellColor}
}
0
Brian