114 votes

Comment personnaliser les couleurs d'arrière-plan/de bordure d'une cellule d'un tableau groupé ?

Je voudrais personnaliser la couleur de l'arrière-plan et de la bordure d'un UITableView de style groupé.

J'ai pu personnaliser la couleur de l'arrière-plan en utilisant ce qui suit :

tableView.contentView.backgroundColor = [UIColor greenColor];

Mais la couleur de la bordure est toujours quelque chose que je ne sais pas comment changer.

Comment puis-je personnaliser ces deux aspects de l'affichage des tableaux de style groupé ?

0 votes

Il est important de s'assurer que la vue IBOutlet de votre UITableViewController est définie, sinon la transparence ne fonctionnera pas !

1 votes

Je ne sais pas comment vous avez réussi à faire fonctionner votre ligne de code. tableView ne semble pas avoir de propriété contentView.

5 votes

Le fil de discussion porte sur l'arrière-plan de UITableViewCell. et non sur UITableView (comme le suggère la question). La vraie réponse serait celle de @dizy.

100voto

Mike Akers Points 4866

UPDATE : Dans iPhone OS 3.0 et ultérieur UITableViewCell a maintenant un backgroundColor qui rend cette opération très facile (surtout en combinaison avec la propriété [UIColor colorWithPatternImage:] initialisateur). Mais je vais laisser la version 2.0 de la réponse ici pour ceux qui en ont besoin


C'est plus difficile que ça ne devrait l'être. Voici comment j'ai fait quand j'ai dû le faire :

Vous devez définir la propriété backgroundView de l'UITableViewCell sur un UIView personnalisé qui dessine la bordure et l'arrière-plan dans les couleurs appropriées. Cette vue doit pouvoir dessiner les bordures selon 4 modes différents : arrondi en haut pour la première cellule d'une section, arrondi en bas pour la dernière cellule d'une section, pas de coins arrondis pour les cellules au milieu d'une section et arrondi sur les 4 coins pour les sections qui contiennent une seule cellule.

Malheureusement, je n'ai pas trouvé comment faire en sorte que ce mode soit défini automatiquement. J'ai donc dû le définir dans la méthode -cellForRowAtIndexPath de UITableViewDataSource.

C'est un véritable casse-tête, mais j'ai confirmé aux ingénieurs d'Apple que c'est actuellement la seule solution.

Mise à jour Voici le code pour cette vue bg personnalisée. Il y a un bug de dessin qui fait que les coins arrondis ont l'air un peu bizarre, mais nous avons changé de design et mis au rebut les arrière-plans personnalisés avant que j'aie pu le corriger. Néanmoins, cela vous sera probablement très utile :

//
//  CustomCellBackgroundView.h
//
//  Created by Mike Akers on 11/21/08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import <UIKit/UIKit.h>

typedef enum  {
    CustomCellBackgroundViewPositionTop, 
    CustomCellBackgroundViewPositionMiddle, 
    CustomCellBackgroundViewPositionBottom,
    CustomCellBackgroundViewPositionSingle
} CustomCellBackgroundViewPosition;

@interface CustomCellBackgroundView : UIView {
    UIColor *borderColor;
    UIColor *fillColor;
    CustomCellBackgroundViewPosition position;
}

    @property(nonatomic, retain) UIColor *borderColor, *fillColor;
    @property(nonatomic) CustomCellBackgroundViewPosition position;
@end

//
//  CustomCellBackgroundView.m
//
//  Created by Mike Akers on 11/21/08.
//  Copyright 2008 __MyCompanyName__. All rights reserved.
//

#import "CustomCellBackgroundView.h"

static void addRoundedRectToPath(CGContextRef context, CGRect rect,
                                 float ovalWidth,float ovalHeight);

@implementation CustomCellBackgroundView
@synthesize borderColor, fillColor, position;

- (BOOL) isOpaque {
    return NO;
}

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        // Initialization code
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    // Drawing code
    CGContextRef c = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(c, [fillColor CGColor]);
    CGContextSetStrokeColorWithColor(c, [borderColor CGColor]);

    if (position == CustomCellBackgroundViewPositionTop) {
        CGContextFillRect(c, CGRectMake(0.0f, rect.size.height - 10.0f, rect.size.width, 10.0f));
        CGContextBeginPath(c);
        CGContextMoveToPoint(c, 0.0f, rect.size.height - 10.0f);
        CGContextAddLineToPoint(c, 0.0f, rect.size.height);
        CGContextAddLineToPoint(c, rect.size.width, rect.size.height);
        CGContextAddLineToPoint(c, rect.size.width, rect.size.height - 10.0f);
        CGContextStrokePath(c);
        CGContextClipToRect(c, CGRectMake(0.0f, 0.0f, rect.size.width, rect.size.height - 10.0f));
    } else if (position == CustomCellBackgroundViewPositionBottom) {
        CGContextFillRect(c, CGRectMake(0.0f, 0.0f, rect.size.width, 10.0f));
        CGContextBeginPath(c);
        CGContextMoveToPoint(c, 0.0f, 10.0f);
        CGContextAddLineToPoint(c, 0.0f, 0.0f);
        CGContextStrokePath(c);
        CGContextBeginPath(c);
        CGContextMoveToPoint(c, rect.size.width, 0.0f);
        CGContextAddLineToPoint(c, rect.size.width, 10.0f);
        CGContextStrokePath(c);
        CGContextClipToRect(c, CGRectMake(0.0f, 10.0f, rect.size.width, rect.size.height));
    } else if (position == CustomCellBackgroundViewPositionMiddle) {
        CGContextFillRect(c, rect);
        CGContextBeginPath(c);
        CGContextMoveToPoint(c, 0.0f, 0.0f);
        CGContextAddLineToPoint(c, 0.0f, rect.size.height);
        CGContextAddLineToPoint(c, rect.size.width, rect.size.height);
        CGContextAddLineToPoint(c, rect.size.width, 0.0f);
        CGContextStrokePath(c);
        return; // no need to bother drawing rounded corners, so we return
    }

    // At this point the clip rect is set to only draw the appropriate
    // corners, so we fill and stroke a rounded rect taking the entire rect

    CGContextBeginPath(c);
    addRoundedRectToPath(c, rect, 10.0f, 10.0f);
    CGContextFillPath(c);  

    CGContextSetLineWidth(c, 1);  
    CGContextBeginPath(c);
    addRoundedRectToPath(c, rect, 10.0f, 10.0f);  
    CGContextStrokePath(c); 
}

- (void)dealloc {
    [borderColor release];
    [fillColor release];
    [super dealloc];
}

@end

static void addRoundedRectToPath(CGContextRef context, CGRect rect,
                                float ovalWidth,float ovalHeight)

{
    float fw, fh;

    if (ovalWidth == 0 || ovalHeight == 0) {// 1
        CGContextAddRect(context, rect);
        return;
    }

    CGContextSaveGState(context);// 2

    CGContextTranslateCTM (context, CGRectGetMinX(rect),// 3
                           CGRectGetMinY(rect));
    CGContextScaleCTM (context, ovalWidth, ovalHeight);// 4
    fw = CGRectGetWidth (rect) / ovalWidth;// 5
    fh = CGRectGetHeight (rect) / ovalHeight;// 6

    CGContextMoveToPoint(context, fw, fh/2); // 7
    CGContextAddArcToPoint(context, fw, fh, fw/2, fh, 1);// 8
    CGContextAddArcToPoint(context, 0, fh, 0, fh/2, 1);// 9
    CGContextAddArcToPoint(context, 0, 0, fw/2, 0, 1);// 10
    CGContextAddArcToPoint(context, fw, 0, fw, fh/2, 1); // 11
    CGContextClosePath(context);// 12

    CGContextRestoreGState(context);// 13
}

0 votes

Pourriez-vous m'aider en utilisant votre code ? => stackoverflow.com/questions/7309580/

2 votes

Pourquoi ne pas utiliser seperatorColor ? Pour moi, cela colore à la fois la ligne de séparation entre les cellules et la bordure.

0 votes

Plutôt que d'utiliser les chemins en arc de cercle de drawRect CG, j'ai utilisé une vue tronquée avec tous les coins arrondis. Je lui donne un Y négatif pour les rangées qui ne sont pas les premières et je lui donne une hauteur excessive pour les rangées qui ne sont pas les dernières.

34voto

dizy Points 3755

Je sais que les réponses concernent la modification des cellules de tableaux groupés, mais au cas où quelqu'un voudrait également modifier la couleur de fond du tableau :

Non seulement vous devez définir :

tableview.backgroundColor = color;

Vous devez également modifier ou supprimer l'affichage de l'arrière-plan :

tableview.backgroundView = nil;

1 votes

Hé, merci. Vous avez donné la bonne réponse à cette question précise.

24voto

Vimal Jain Points 251

Tout d'abord, merci pour ce code. J'ai fait quelques modifications de dessin dans cette fonction pour supprimer le problème de coin de dessin.

-(void)drawRect:(CGRect)rect 
{
    // Drawing code

    CGContextRef c = UIGraphicsGetCurrentContext();
    CGContextSetFillColorWithColor(c, [fillColor CGColor]);
    CGContextSetStrokeColorWithColor(c, [borderColor CGColor]);
    CGContextSetLineWidth(c, 2);

    if (position == CustomCellBackgroundViewPositionTop) {

        CGFloat minx = CGRectGetMinX(rect) , midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ;
        CGFloat miny = CGRectGetMinY(rect) , maxy = CGRectGetMaxY(rect) ;
        minx = minx + 1;
        miny = miny + 1;

        maxx = maxx - 1;
        maxy = maxy ;

        CGContextMoveToPoint(c, minx, maxy);
        CGContextAddArcToPoint(c, minx, miny, midx, miny, ROUND_SIZE);
        CGContextAddArcToPoint(c, maxx, miny, maxx, maxy, ROUND_SIZE);
        CGContextAddLineToPoint(c, maxx, maxy);

        // Close the path
        CGContextClosePath(c);
        // Fill & stroke the path
        CGContextDrawPath(c, kCGPathFillStroke);        
        return;
    } else if (position == CustomCellBackgroundViewPositionBottom) {

        CGFloat minx = CGRectGetMinX(rect) , midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ;
        CGFloat miny = CGRectGetMinY(rect) , maxy = CGRectGetMaxY(rect) ;
        minx = minx + 1;
        miny = miny ;

        maxx = maxx - 1;
        maxy = maxy - 1;

        CGContextMoveToPoint(c, minx, miny);
        CGContextAddArcToPoint(c, minx, maxy, midx, maxy, ROUND_SIZE);
        CGContextAddArcToPoint(c, maxx, maxy, maxx, miny, ROUND_SIZE);
        CGContextAddLineToPoint(c, maxx, miny);
        // Close the path
        CGContextClosePath(c);
        // Fill & stroke the path
        CGContextDrawPath(c, kCGPathFillStroke);    
        return;
    } else if (position == CustomCellBackgroundViewPositionMiddle) {
        CGFloat minx = CGRectGetMinX(rect) , maxx = CGRectGetMaxX(rect) ;
        CGFloat miny = CGRectGetMinY(rect) , maxy = CGRectGetMaxY(rect) ;
        minx = minx + 1;
        miny = miny ;

        maxx = maxx - 1;
        maxy = maxy ;

        CGContextMoveToPoint(c, minx, miny);
        CGContextAddLineToPoint(c, maxx, miny);
        CGContextAddLineToPoint(c, maxx, maxy);
        CGContextAddLineToPoint(c, minx, maxy);

        CGContextClosePath(c);
        // Fill & stroke the path
        CGContextDrawPath(c, kCGPathFillStroke);    
        return;
    }
}

0 votes

La largeur de la ligne avec votre code est d'environ 2 px. Lorsque j'essaie de régler CGContextSetLineWidth sur 1, la ligne est toujours trop épaisse. Comment cela se fait-il ?

0 votes

J'ai la même question ? pourquoi il est plus épais que celui du système.

16voto

Aliz Raksi Points 161

Merci pour le code, c'est exactement ce que je cherchais. J'ai également ajouté le code suivant au code de Vimal, pour implémenter le cas d'une cellule CustomCellBackgroundViewPositionSingle. (Les quatre coins sont arrondis).

else if (position == CustomCellBackgroundViewPositionSingle)
{
        CGFloat minx = CGRectGetMinX(rect) , midx = CGRectGetMidX(rect), maxx = CGRectGetMaxX(rect) ;
        CGFloat miny = CGRectGetMinY(rect) , midy = CGRectGetMidY(rect) , maxy = CGRectGetMaxY(rect) ;
        minx = minx + 1;
        miny = miny + 1;

        maxx = maxx - 1;
        maxy = maxy - 1;

        CGContextMoveToPoint(c, minx, midy);
        CGContextAddArcToPoint(c, minx, miny, midx, miny, ROUND_SIZE);
        CGContextAddArcToPoint(c, maxx, miny, maxx, midy, ROUND_SIZE);
        CGContextAddArcToPoint(c, maxx, maxy, midx, maxy, ROUND_SIZE);
        CGContextAddArcToPoint(c, minx, maxy, minx, midy, ROUND_SIZE);

        // Close the path
        CGContextClosePath(c);
        // Fill & stroke the path
        CGContextDrawPath(c, kCGPathFillStroke);                
        return;     
}

13voto

Justin Anderson Points 986

Une chose que j'ai rencontrée avec le code CustomCellBackgroundView ci-dessus de Mike Akers et qui pourrait être utile à d'autres :

cell.backgroundView ne se redessine pas automatiquement lorsque les cellules sont réutilisées, et les modifications apportées à la variable de position de l'arrière-plan n'affectent pas les cellules réutilisées. Cela signifie que les tableaux longs auront un dessin incorrect cell.backgroundViews compte tenu de leurs positions.

Pour résoudre ce problème sans avoir à créer un nouveau backgroundView à chaque fois qu'une ligne est affichée, il faut appeler [cell.backgroundView setNeedsDisplay] à la fin de votre -[UITableViewController tableView:cellForRowAtIndexPath:] . Ou, pour une solution plus réutilisable, modifiez le paramètre de position de CustomCellBackgroundView afin d'y inclure un élément [self setNeedsDisplay] .

0 votes

Bonne idée de remplacer la commande -setPosition

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