Como personalizar a cor de plano de fundo de um UITableViewCell?

188

Gostaria de personalizar o plano de fundo (e talvez também a borda) de todos os UITableViewCells dentro do meu UITableView. Até agora não consegui personalizar esse material, por isso tenho várias células de fundo branco, que é o padrão.

Existe uma maneira de fazer isso com o iPhone SDK?

jpm
fonte

Respostas:

193

Você precisa definir o backgroundColor do conteúdo da célula para a sua cor. Se você usar acessórios (como setas de divulgação, etc.), eles aparecerão em branco; portanto, você poderá rolar versões personalizadas deles.

Ben Gottlieb
fonte
108
por exemplo, myCell.contentView.backgroundColor = [UIColor greenColor];
JoBu1324
1
A resposta de vlado.grigorov é mais flexível - consulte a resposta de William Denniss
#
3
Algum link sobre como criar UITableViewCellAccessoryCheckmark, por exemplo? Obrigado.
Dan Rosenstark 9/09/11
6
Para vê-lo, por vezes, você precisa definir:cell.textLabel.backgroundColor = [UIColor clearColor];
Evan Moran
205

Aqui está a maneira mais eficiente que me deparei para resolver esse problema, use o método delegado willDisplayCell (isso também cuida da cor branca do plano de fundo do rótulo de texto ao usar cell.textLabel.text e / ou cell.detailTextLabel.text ):

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath { ... }

Quando esse método delegado é chamado, a cor da célula é controlada pela célula, e não pela exibição da tabela, como quando você usa:

- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath { ... }

Portanto, no corpo do método delegado da célula, adicione o código a seguir para alternar cores das células ou use a chamada de função para tornar todas as células da tabela da mesma cor.

if (indexPath.row % 2)
{
    [cell setBackgroundColor:[UIColor colorWithRed:.8 green:.8 blue:1 alpha:1]];
}
else [cell setBackgroundColor:[UIColor clearColor]];

Esta solução funcionou bem na minha circunstância ...

Nathan B.
fonte
Esta é uma solução mais limpa. A maioria das outras soluções requer uma subclasse de UITableViewCell. A solução do vlado.grigorov não funciona para mim.
precisa saber é o seguinte
De fato, e esse é o método que a própria Apple recomenda de acordo com várias apresentações da WWDC que eu já vi.
93010 Mike Weller
Agradável - EXCETO quando você precisar adicionar novas linhas no topo da lista. Este método torna todas as adições da mesma cor. A atualização corrige, mas leva um tempo desnecessário. Descoberto ontem ...
JOM 16/04
Isso parece funcionar bem, exceto ao usar o Core Data. Novas células adicionadas por meio de um NSFetchedResultsController parecem não chamar willDisplayCell corretamente. Eu estou em uma perda fazê-lo funcionar ...
radven
A linha equivalente para definir a cor do fundo em Swift 2.0:cell.backgroundColor = UIColor.clearColor
kbpontius
104

Isso é realmente simples, pois o OS 3.0 apenas define a cor de fundo da célula no método willDisplayCell. Você não deve definir a cor no cellForRowAtIndexPath.

Isso funciona para os estilos simples e agrupado:

Código:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    cell.backgroundColor = [UIColor redColor];
}

PS: Aqui o extrato da documentação para willDisplayCell:

"Uma exibição de tabela envia essa mensagem ao seu delegado antes de usar a célula para desenhar uma linha, permitindo que o delegado personalize o objeto da célula antes de ser exibido. Esse método oferece ao delegado a chance de substituir as propriedades baseadas em estado definidas anteriormente por a exibição da tabela, como a seleção e a cor do plano de fundo. Depois que o delegado retorna, a exibição da tabela define apenas as propriedades alfa e de quadro e, em seguida, apenas ao animar linhas quando elas deslizam para dentro ou para fora ".

Encontrei esta informação neste post da colionel . Agradecê-lo!

Seba
fonte
3
Este deve ser marcado como a resposta correta como você não tem sequer a qualquer coisa se você tem um disclosureIndiator
Ashish Awaghad
1
Isso não funciona se você quiser uma cor de plano de fundo de célula diferente para o plano de exibição de tabela para mim.
Chris
Para célula de grupo, você pode configurá-lo em cellForRow
Sharen Eayrs
58

A melhor abordagem que encontrei até agora é definir uma exibição em segundo plano da célula e limpar o segundo plano das subvisões de célula. Obviamente, isso fica bem em tabelas com estilo indexado apenas, não importa com ou sem acessórios.

Aqui está uma amostra em que o fundo da célula está amarelo ofegante:

UIView* backgroundView = [ [ [ UIView alloc ] initWithFrame:CGRectZero ] autorelease ];
backgroundView.backgroundColor = [ UIColor yellowColor ];
cell.backgroundView = backgroundView;
for ( UIView* view in cell.contentView.subviews ) 
{
    view.backgroundColor = [ UIColor clearColor ];
}
Vladimir Grigorov
fonte
1
Se você fizer isso, defina também a propriedade opaca como NO.
Lily Ballard
11
Usar controles transparentes de células não é realmente recomendado. O desempenho da rolagem será afetado muito, e é por isso que a Apple sempre recomenda usar controles opacos.
Mike Weller
3
No iOS 4.2 e posterior, parece que o loop não é mais necessário.
Frank Schmitt
Muito agradável. Funciona perfeito ao usar vistas acessórias !!
ryang
19

Basta colocar isso no seu arquivo de classe de delegação UITableView (.m):

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell  forRowAtIndexPath:(NSIndexPath *)indexPath 
{
    UIColor *color = ((indexPath.row % 2) == 0) ? [UIColor colorWithRed:255.0/255 green:255.0/255 blue:145.0/255 alpha:1] : [UIColor clearColor];
    cell.backgroundColor = color;
}
ENTALHE
fonte
7

Concordo com o Seba, tentei definir minha cor de linha alternada no método delegado rowForIndexPath, mas estava obtendo resultados inconsistentes entre 3,2 e 4,2. O seguinte funcionou muito bem para mim.

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {

    if ((indexPath.row % 2) == 1) {
        cell.backgroundColor = UIColorFromRGB(0xEDEDED);
        cell.textLabel.backgroundColor = UIColorFromRGB(0xEDEDED);
        cell.selectionStyle = UITableViewCellSelectionStyleGray;
    }
    else
    {
        cell.backgroundColor = [UIColor whiteColor];
        cell.selectionStyle = UITableViewCellSelectionStyleGray;
    }

}
cipherz
fonte
1
Ainda não entendo por que defini-lo no willDisplayCell faz alguma diferença. É chamado assim mesmo se implementamos isso ou não, certo?
Sharen Eayrs
6

Depois de experimentar todas as soluções diferentes, o método a seguir é o mais elegante. Mude a cor no seguinte método delegado:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (...){
        cell.backgroundColor = [UIColor blueColor];
    } else {
        cell.backgroundColor = [UIColor whiteColor];
    }
}
Jim Huang
fonte
4

O vlado.grigorov tem alguns bons conselhos - a melhor maneira é criar um backgroundView e dar a ela uma cor, definindo todo o resto para o clearColor. Além disso, acho que dessa maneira é a única maneira de limpar a cor corretamente (tente a amostra - mas defina 'clearColor' em vez de 'yellowColor'), que é o que eu estava tentando fazer.

William Denniss
fonte
Uma vantagem dessa abordagem é que você pode manter a cor uma propriedade de tempo de design no Interface Builder. Um problema de design a menos que requer interação com o desenvolvedor.
whitneyland
1
cell.backgroundView = [[[alocação de UIView] initWithFrame: cell.bounds] autorelease]; cell.backgroundView.backgroundColor = [UIColor redColor];
18713 Brian Brian
3

A personalização do plano de fundo de uma célula de exibição de tabela acaba se tornando uma abordagem "tudo ou nada". É muito difícil alterar a cor ou a imagem usada no plano de fundo de uma célula de conteúdo de uma maneira que não pareça estranha.

O motivo é que a célula realmente abrange a largura da visualização. Os cantos arredondados são apenas parte de seu estilo de desenho e a exibição de conteúdo fica nessa área.

Se você alterar a cor da célula de conteúdo, os bits brancos ficarão visíveis nos cantos. Se você alterar a cor da célula inteira, terá um bloco de cores que mede a largura da visualização.

Definitivamente, você pode personalizar uma célula, mas não é tão fácil quanto você imagina a princípio.

Andrew Grant
fonte
1
Definitivamente, isso é verdade para células em tabelas agrupadas, mas as tabelas simples não precisam se preocupar muito com isso. Uma célula sem adornos e sem acessórios deve ficar bem.
Ben Gottlieb
Ben - bom argumento. Eu uso principalmente tabelas agrupadas, mas como você menciona, as tabelas simples não sofrem com nenhum desses problemas.
Andrew Grant
3

Crie uma visualização e defina-a como visualização em segundo plano da célula

UIView *lab = [[UIView alloc] initWithFrame:cell.frame];
            [lab setBackgroundColor:[UIColor grayColor]];
            cell.backgroundView = lab;
            [lab release];
Senthil
fonte
3

Para estender a resposta de N.Berendt - Se você deseja definir a cor da célula com base em algum estado no objeto de dados da célula, no momento você está configurando o restante das informações para a célula da tabela, que normalmente ocorre quando você está no cellForRowAtIndexPath, você pode fazer isso substituindo o método willDisplayCell para definir a cor de plano de fundo da célula na cor de plano de fundo da exibição de conteúdo - isso evita que o problema dos planos de fundo do botão de divulgação, etc. não esteja certo, mas ainda permita controlar a cor no método cellForRowAtIndexPath onde você está fazendo toda a sua outra personalização de célula.

Portanto: se você adicionar este método ao seu delegado de exibição de tabela:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    cell.backgroundColor = cell.contentView.backgroundColor;
}

Em seu método cellForRowAtIndexPath, você pode fazer:

if (myCellDataObject.hasSomeStateThatMeansItShouldShowAsBlue) {
    cell.contentView.backgroundColor = [UIColor blueColor];
}

Isso evita a necessidade de recuperar seus objetos de dados novamente no método willDisplayCell e também economiza dois locais onde você faz a alfaiataria / customização da célula da tabela - toda a customização pode ser feita no método cellForRowAtIndexPath.

gamozzii
fonte
3

Crie uma imagem para usar como plano de fundo com o Photoshop ou gimp e chame-a de minha imagem. Em seguida, adicione este método à sua classe tableViewController:

- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
    UIImage *cellImage = [UIImage imageNamed:@"myimage.png"];//myimage is a 20x50 px with  gradient  color created with gimp
    UIImageView *cellView = [[UIImageView alloc] initWithImage:cellImage];
    cellView.contentMode = UIContentViewModeScaleToFill;
    cell.backgroundView = cellView;
    //set the background label to clear
    cell.titleLabel.backgroundColor= [UIColor clearColor];
}

Isso funcionará também se você tiver definido o UITableView como personalizado no inspetor de atributos.

Davide
fonte
2

Minha solução é adicionar o seguinte código ao evento cellForRowAtIndexPath:

UIView *solidColor = [cell viewWithTag:100];
if (!solidColor) {

    solidColor = [[UIView alloc] initWithFrame:cell.bounds];
    solidColor.tag = 100; //Big tag to access the view afterwards
    [cell addSubview:solidColor];
    [cell sendSubviewToBack:solidColor];
    [solidColor release];
}
solidColor.backgroundColor = [UIColor colorWithRed:254.0/255.0
                                             green:233.0/255.0
                                              blue:233.0/255.0
                                             alpha:1.0];

Funciona sob quaisquer circunstâncias, mesmo com botões de divulgação, e é melhor para sua lógica atuar no estado de cor das células no cellForRowAtIndexPath do que no evento cellWillShow que eu acho.

albertoFlagSolutions
fonte
1

Subclasse UITableViewCell e adicione isso na implementação:

-(void)layoutSubviews
{
    [super layoutSubviews];
    self.backgroundColor = [UIColor blueColor];
}
JonahGabriel
fonte
1
    UIView *bg = [[UIView alloc] initWithFrame:cell.frame];
    bg.backgroundColor = [UIColor colorWithRed:175.0/255.0 green:220.0/255.0 blue:186.0/255.0 alpha:1]; 
    cell.backgroundView = bg;
    [bg release];
Bhavesh Nayi
fonte
1

Isso funcionará no último Xcode.

-(UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath {
    cell.backgroundColor = [UIColor grayColor];
}
Sameera R.
fonte
0

Tente o seguinte:

- (void)tableView:(UITableView *)tableView1 willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
    [cell setBackgroundColor:[UIColor clearColor]];
    tableView1.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed: @"Cream.jpg"]];
}
Pang
fonte