5 votes

selectedBackgroundView sur UITableViewCell s'applique à toutes les vues de la cellule

J'ai une cellule de tableau qui affiche l'image d'un utilisateur, son nom et un peu de texte. L'image de l'utilisateur fait 50x50, mais je veux une bordure autour d'elle, alors je règle la vue pour centrer l'image et je règle le cadre sur 52x52, puis je règle la couleur d'arrière-plan de cette vue sur la couleur de ma bordure. Une bordure de 1 pixel apparaît alors autour de l'image.

Je souhaite également afficher une bordure de 30 pixels de large à droite de la cellule lorsque celle-ci est sélectionnée. J'ai essayé de le faire en créant une UIView de la taille du cadre de la cellule, puis en ajoutant une sous-vue à cette vue avec une UIView de la largeur et de la couleur d'arrière-plan souhaitées. J'ai ensuite défini cette vue comme étant la selectedBackgroundView de la cellule.

Le problème est que le selectedBackgroundView de la cellule est appliqué à l'arrière-plan de tous les points de vue à l'intérieur de la cellule. Ainsi, lorsque je sélectionne une cellule, la "bordure" de l'image prend la couleur d'arrière-plan de la cellule sélectionnée, et l'autre "bordure" de 30 px que j'ajoute prend également cette couleur d'arrière-plan.

Code à l'intérieur de ma celluleForRowAtIndexPath :

cell = (UserCellView *) currentObject;

UIView *c = [[UIView alloc ] initWithFrame:CGRectMake(0, 0, 30, cell.frame.size.height)];
c.backgroundColor = [[UIColor alloc] initWithRed:64/255.0 green:64/255.0 blue:64/255.0 alpha:1.0];

UIView *v = [[UIView alloc ] initWithFrame:cell.frame];             
v.backgroundColor = [[UIColor alloc] initWithRed:35/255.0 green:35/255.0 blue:35/255.0 alpha:1.0];              

[v addSubview:c];       

cell.selectedBackgroundView = v;

[c release];
[v release];

11voto

tc. Points 23958

Je suppose que vous ne l'avez pas fait en fait a testé ce qui se passe pour former votre analyse selon laquelle il "est appliqué à l'arrière-plan de toutes les vues à l'intérieur de la cellule".

J'ai fait quelque chose comme ça :

@interface TestView : UIView {
}
@end
@implementation TestView
-(void)setBackgroundColor:(UIColor*)c {
  // Breakpoint here.
  NSLog("setBackgroundColor: %@",c);
  [super setBackgroundColor:c];
}
@end

...

UIView * v = [[[UIView alloc] initWithFrame:(CGRect){{0,0},{20,20}}] autorelease];
v.backgroundColor = [UIColor magentaColor];
UIView * v2 = [[[TestView alloc] initWithFrame:(CGRect){{5,5},{10,10}}] autorelease];
v2.backgroundColor = [UIColor yellowColor];
[v addSubview:v2];
cell.selectedBackgroundView = v;

Le résultat final est que -setBackgroundColor: est appelé à partir de -[UITableViewCell _setOpaque:forSubview:] lorsque la vue est sélectionnée, avec quelque chose comme UIDeviceWhiteColorSpace 0 0 (c'est-à-dire [UIColor clearColor] ).

En d'autres termes, la couleur d'arrière-plan de certains sous-affichages est réglée sur [UIColor clearColor] pendant que la cellule est sélectionnée, ce qui permet à selectedBackgroundView de transparaître. I penser Cela se produit parce qu'une optimisation courante consiste à donner aux textLabel / detailTextLabel la couleur d'arrière-plan du tableau (par exemple, le blanc) afin de dessiner plus rapidement, mais cela signifie que la couleur d'arrière-plan doit être réinitialisée lorsque la cellule est sélectionnée.

La solution la plus simple consiste à utiliser une image à la place : une image de 1 par 1 pixel de la bonne couleur dans un UIImageView fonctionnera, bien qu'elle soit un peu désordonnée. (J'ai rencontré ce problème en dessinant des lignes de séparation personnalisées avec des UIViews d'une hauteur de 1 pixel, et j'ai donc simplement inclus le séparateur dans l'image d'arrière-plan).

Une solution alternative consiste à utiliser un CALayer à la place : Ajoutez une sous-couche 52x52 à la couche de UIImageView, et définissez la couleur d'arrière-plan de la sous-couche. Je suis presque sûr que UITableViewCell ne fait que parcourir la hiérarchie de la vue, et qu'il devrait donc ignorer les couches personnalisées. (Le gros inconvénient des calques est qu'ils ne se redimensionnent pas automatiquement, ce qui les rend inadaptés à mes besoins, et signifie que la bordure droite de 30px ne se redimensionnera pas automatiquement).

Une solution de contournement consiste à sous-classer les vues concernées et à ignorer -setBackgroundColor: s'il est égal à [UIColor clearColor] .

1voto

Roee Shenberg Points 417

Une solution simple mais pénible à maintenir consiste à surcharger setSelected:animated : et setHighlighted:animated : avec des implémentations réinitialisant les différents arrière-plans que vous souhaitez. Quelque chose du genre :

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];
    self.childView.backgroundColor = [UIColor blueColor]; // whichever you want
}

1voto

Andrew Gene Points 175

Ajoutez d'abord ceci à votre fichier

#import <QuartzCore/QuartzCore.h>

Transformez ensuite votre vue en image avec...

    UIView *rowView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 1.0, 60.0)];
    rowView.backgroundColor = [UIColor colorWithRed:35/255.0 green:35/255.0 blue:35/255.0 alpha:1.0];        

    UIGraphicsBeginImageContext(rowView.bounds.size);
    [rowView.layer renderInContext:UIGraphicsGetCurrentContext()];
    UIImage *yourImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();

Au lieu d'ajouter une UIView à votre cellule, ajoutez simplement une UIImageView avec "yourImage".

0voto

Mike Abdullah Points 9464

Une solution simple, si la vue concernée peut être une sous-classe personnalisée, consiste à surcharger les éléments suivants -setBackgroundColor:

- (void)setBackgroundColor:(UIColor *)color
{
    // Ignore requests and do nothing
}

Ainsi UITableViewCell ne sera pas prise en compte. Le code de la vue personnalisée qui souhaite réellement définir la couleur d'arrière-plan doit appeler super :

- (void)setColor:(UIColor *)color
{
    [super setBackgroundColor:color];
}

(ou pourrait probablement envoyer un message au CALayer directement)

-5voto

Aaron Saunders Points 20454

Vous devrez personnaliser le contentView des cellules et gérer le délégué tableView:cellForRowAtIndexPath

Voir l'affichage ici

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