114 votes

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

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

J'ai pu personnaliser la couleur de fond en utilisant les éléments suivants:

 tableView.contentView.backgroundColor = [UIColor greenColor];
 

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

Comment personnaliser ces deux aspects de la vue de table de style groupé?

100voto

Mike Akers Points 4866

Mise à JOUR: l'iPhone OS 3.0 et versions ultérieures UITableViewCell a maintenant un backgroundColor propriété qui rend ce vraiment facile (surtout en combinaison avec l' [UIColor colorWithPatternImage:] initialiseur). Mais je vais laisser la version 2.0 de la réponse ici pour quelqu'un qui en a besoin...


C'est plus difficile qu'il doit être vraiment. Voici comment je l'ai fait quand j'ai eu à le faire:

Vous devez définir le UITableViewCell de backgroundView propriété personnalisée UIView qui dessine la frontière et le fond lui-même dans les couleurs appropriées. Ce point de vue doit être en mesure de tracer les frontières dans les 4 modes différents, arrondie sur le dessus pour la première cellule dans une section arrondie sur le bas de la dernière cellule dans une section, pas de coins arrondis pour les cellules dans le milieu de la partie, et arrondi sur les 4 coins pour les sections qui contiennent une cellule.

Malheureusement, je ne pouvais pas comprendre comment avoir ce jeu de mode automatiquement, donc j'ai dû mettre dans le UITableViewDataSource-cellForRowAtIndexPath méthode.

C'est un vrai PITA, mais j'ai confirmé avec les ingénieurs d'Apple que ce n'est actuellement le seul moyen.

Mise à jour Voici le code pour que la coutume bg vue. Il y a un bug d'affichage qui rend les coins arrondis à l'air un peu drôle, mais nous avons déménagé pour un design différent et mises au rebut de l'arrière-plans personnalisés avant j'avais une chance de le résoudre. Encore ce sera probablement très utile pour vous:

//
//  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
}

34voto

dizy Points 3755

Je sais que les réponses concernent la modification de cellules de tableau groupées, mais si quelqu'un souhaite également modifier la couleur d'arrière-plan de la tableview:

Non seulement vous devez définir:

 tableview.backgroundColor = color;
 

Vous devez également modifier ou supprimer la vue d’arrière-plan:

 tableview.backgroundView = nil;  
 

24voto

Vimal Jain Points 251

Tout d'abord merci pour ce code. J'ai apporté quelques modifications au dessin dans cette fonction pour supprimer les problèmes de coin liés au 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;
    }
}
 

16voto

Aliz Raksi Points 161

Merci pour le code, c'est juste ce que je cherchais. J'ai également ajouté le code suivant au code de Vimal, pour implémenter la casse 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 couru, les CustomCellBackgroundView code de Mike Akers, qui pourrait être utile à d'autres:

cell.backgroundView ne sont pas automatiquement redessiné lorsque les cellules sont réutilisés, et les changements à la backgroundView position du var n'affectent pas réutilisé les cellules. Que signifie de longues tables ont mal rédigé cell.backgroundViews compte tenu de leur position.

Pour résoudre ce sans avoir à créer un nouveau backgroundView chaque fois qu'une ligne est affichée, appelez - [cell.backgroundView setNeedsDisplay] à la fin de votre -[UITableViewController tableView:cellForRowAtIndexPath:]. Ou pour un plus réutilisable solution, remplacer CustomCellBackgroundView position du setter pour inclure un [self setNeedsDisplay].

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