71 votes

UIView backgroundColor disparaît lorsque UITableViewCell est sélectionné

J'ai un simple tableViewCell construit dans interface builder. Il contient un UIView qui contient une image. Maintenant, lorsque je sélectionne la cellule, l'arrière-plan de sélection bleu par défaut est affiché, mais la backgroundColor de mon UIView a disparu.

Le fichier d'implémentation de mon UITableViewCell ne fait rien de spécial. Il se contente d'initier et de retourner self et tout ce que je fais dans setSelected est d'appeler super.

Comment faire pour que la couleur d'arrière-plan de mon UIView s'affiche lorsque le tableView est sélectionné ?

0 votes

Quels autres éléments d'interface se trouvent dans la vue, qui sont couverts par la couleur de sélection des cellules ?

0 votes

Actuellement, c'est juste une image. Il est destiné à faire en sorte que l'image ressemble à une photographie. Plus tard, j'ajouterai également une étiquette.

108voto

Brooks Points 775

Le problème ici est que la [super] mise en œuvre de l'option

- (void) setSelected:(BOOL) selected animated:(BOOL) animated;

définit toutes les couleurs d'arrière-plan dans le UITableViewCell à rgba(0,0,0,0). Pourquoi ? Peut-être pour nous donner des sueurs froides ?

Ce n'est pas que des vues entières disparaissent (comme le prouve le fait que si vous modifiez les propriétés de bordure du calque des vues, celles-ci sont conservées).

Voici la séquence d'appels de fonction qui résulte du fait de toucher une cellule

  1. setHighlighted
  2. toucheEnded
  3. layoutSubviews
  4. willSelectRowAtIndexPath (côté délégué)
  5. setSelected ( !!! c'est ici que toutes les couleurs d'arrière-plan de votre vue doivent disparaître)
  6. didSelectRowAtIndexPath (côté délégué)
  7. setSelected (encore) (Il est intéressant de noter que les couleurs de fond ne sont pas effacées lors de cet appel. Quelle est l'étrangeté qui se passe dans cette super méthode ?)
  8. layoutSubviews (encore)

Vos options sont donc les suivantes

  1. Remplacer - (void) setSelected :(BOOL) selected animated :(BOOL) animated ; sans appeler [super setSelected:selected animated:animated] . Cela vous donnera l'implémentation la plus correcte techniquement car a) le code est enveloppé dans la sous-classe UITableViewCell et b) parce qu'il n'est appelé qu'en cas de besoin (enfin deux fois en cas de besoin, mais il y a peut-être un moyen de contourner cela). L'inconvénient est que vous devrez réimplémenter toutes les fonctions nécessaires (par opposition aux fonctions inutiles d'effacement des couleurs) de setSelected. Ne me demandez pas encore comment remplacer correctement setSelected. Votre réponse est aussi bonne que la mienne pour le moment (soyez patient, j'éditerai cette réponse dès que j'aurai trouvé).
  2. Réaffirmer les couleurs de fond dans didSelectRowAtIndexPath . Ce n'est pas si génial car cela place ce qui devrait être du code d'instance en dehors de l'instance. L'avantage est qu'il n'est appelé que lorsqu'il est nécessaire, contrairement à ...
  3. Réaffirmer les couleurs de fond dans layoutSubviews . Ce n'est pas génial du tout car layoutSubviews est appelé des MILLIONS de fois ! Il est appelé chaque fois que la table se rafraîchit, chaque fois qu'elle défile, chaque fois que votre grand-mère obtient une permission... sérieusement, un million de fois. Cela signifie qu'il y a beaucoup de réaffirmations inutiles en arrière-plan et beaucoup de surcharge de traitement supplémentaire. Le bon côté des choses, c'est que le code est placé dans la sous-classe UITableViewCell, ce qui est agréable.

Malheureusement, la réaffirmation des couleurs d'arrière-plan dans setHighlighted ne sert à rien car setHighlighted est appelé avant que toutes les couleurs d'arrière-plan ne soient définies à [r:0 b:0 g:0 a:0] par le premier appel à setSelected.

//TODO : Donner une bonne description de la façon de remplacer setSelected (stay tuned)

1 votes

Excellente réponse. C'est tout à fait logique ! Je vais rester à l'écoute pour le passage en force ;-)

0 votes

Juste un suivi. J'ai beaucoup travaillé sur ce sujet mais je n'ai toujours pas trouvé ce que j'appellerais une solution propre et générique pour remplacer setSelected. Si/quand je le fais, je posterai plus d'informations.... Bon codage

1 votes

Si vous définissez la couleur d'arrière-plan de la UIView dans setSelected, vous devez également la définir dans setHighlighted, sinon vous risquez de voir un scintillement.

72voto

mientus Points 2188
- (void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated
{
    UIColor *backgroundColor = self.channelImageView.backgroundColor;
    [super setHighlighted:highlighted animated:animated];
    self.channelImageView.backgroundColor = backgroundColor;
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    UIColor *backgroundColor = self.channelImageView.backgroundColor;
    [super setSelected:selected animated:animated];
    self.channelImageView.backgroundColor = backgroundColor;
}

1 votes

Excellente solution. Beaucoup plus propre que toutes les solutions de sous-classe et de CALayer.

0 votes

Merci ! Votre solution est la meilleure !

0 votes

C'est la réponse la plus utile pour moi. Modifié il légèrement pour mon cas d'utilisation (plusieurs cellules avec plusieurs vues de fond verrouillées), mais félicitations pour la solution qui fonctionne !

16voto

ZeCodea Points 591

Auparavant, j'ai fait ce que @P5ycH0 a dit (image 1x1 étirée), mais en suivant @Brooks, j'ai pensé que le fait d'écraser -(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated dans ma coutume UITableViewCell et de réinitialiser les couleurs d'arrière-plan après avoir appelé [super setHighlighted:highlighted animated:animated]; conserve mes couleurs d'arrière-plan lorsque la cellule est sélectionnée/mise en évidence

-(void)setHighlighted:(BOOL)highlighted animated:(BOOL)animated {
    [super setHighlighted:highlighted animated:animated];
    myView.backgroundColor = myColor;
}

0 votes

Merci, je l'ai cherché pendant 2 jours.

0 votes

Vous m'avez fait gagner du temps. Merci beaucoup.

0 votes

Je pense que cela setHighlighted la fonction est créée pour ajouter un comportement personnalisé lorsque la cellule est sélectionnée, btw bon travail

4voto

lavoy Points 600

Brooks a une excellente explication pour expliquer pourquoi cela se produit, mais je pense avoir une meilleure solution.

Dans votre sous-vue, remplacez setBackgroundColor: à la couleur que vous voulez. Le setter sera toujours appelé, mais seule la couleur spécifiée sera appliquée.

- (void)setBackgroundColor:(UIColor *)backgroundColor {
    [super setBackgroundColor:[UIColor whiteColor]];
}

3voto

P5ycH0 Points 1100

Ok, la perte de la couleur d'arrière-plan d'une classe UIView est un comportement normal lorsqu'elle se trouve dans une cellule de tableview sélectionnée. Je n'ai pas réussi à trouver comment empêcher cela. Maintenant, j'ai juste remplacé l'UIView par un UIImageView contenant un pixel blanc 1x1 étiré. C'est moche, mais ça marche.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X