Como definir a largura de uma célula em um UITableView em estilo agrupado

107

Estou trabalhando nisso há cerca de 2 dias, então pensei em compartilhar meus aprendizados com você.

A questão é: É possível diminuir a largura de uma célula em um UITableView agrupado?

A resposta é não.

Mas existem duas maneiras de contornar esse problema.

Solução # 1: Uma tabela mais fina É possível alterar o quadro de tableView, para que a tabela fique menor. Isso resultará em UITableView renderizando a célula interna com a largura reduzida.

Uma solução para isso pode ser assim:

-(void)viewWillAppear:(BOOL)animated
{
    CGFloat tableBorderLeft = 20;
    CGFloat tableBorderRight = 20;

    CGRect tableRect = self.view.frame;
    tableRect.origin.x += tableBorderLeft; // make the table begin a few pixels right from its origin
    tableRect.size.width -= tableBorderLeft + tableBorderRight; // reduce the width of the table
    tableView.frame = tableRect;
}

Solução # 2: tendo células renderizadas por imagens

Esta solução é descrita aqui: http://cocoawithlove.com/2009/04/easy-custom-uitableview-drawing.html

Eu espero que esta informação seja útil pra você. Levei cerca de 2 dias para tentar várias possibilidades. Isso é o que sobrou.

Tomen
fonte
3
Acho que isso deveria ter sido configurado como uma pergunta com apenas a segunda linha ("A pergunta é: ..."), então a Solução # 1 e a Solução # 2 postadas como duas respostas separadas, com uma delas sendo aceita. Então, se outros usuários adicionarem suas próprias respostas, e um deles acabar sendo melhor, a resposta aceita pode ser alterada posteriormente.
GeneralMike de

Respostas:

226

Uma maneira melhor e mais limpa de conseguir isso é subclassificar UITableViewCell e substituir seu -setFrame:método desta forma:

- (void)setFrame:(CGRect)frame {
    frame.origin.x += inset;
    frame.size.width -= 2 * inset;
    [super setFrame:frame];
}

Por que está melhor? Porque os outros dois são piores.

  1. Ajuste a largura da visualização da mesa em -viewWillAppear:

    Em primeiro lugar, isso não é confiável, o superview ou o controlador de visualização pai pode ajustar o quadro de visualização da tabela mais tarde -viewWillAppear:é chamado. Claro, você pode criar uma subclasse e sobrescrever -setFrame:para seu UITableView da mesma forma que faço aqui para UITableViewCells. No entanto, criar subclasses de UITableViewCells é uma maneira muito comum, leve e da Apple.

    Em segundo lugar, se seu UITableView tem backgroundView, você não quer que seu backgroundView seja estreitado. Manter a largura de backgroundView enquanto reduz a largura de UITableView não é um trabalho trivial, sem mencionar que expandir subvisualizações além de sua supervisão não é uma coisa muito elegante de se fazer em primeiro lugar.

  2. Renderização de célula personalizada para fingir uma largura mais estreita

    Para fazer isso, você deve preparar imagens de fundo especiais com margens horizontais e fazer o layout de subvisualizações das células para acomodar as margens. Em comparação, se você simplesmente ajustar a largura de toda a célula, o redimensionamento automático fará todo o trabalho para você.

an0
fonte
2
esta é uma solução bonita e elegante, eu fiz isso em uma categoria :) Eu também observaria que quanto mais objetos transparentes, mais carga de CPU :)
mister koz
11
@misterkoz - uma palavra de cautela: alguns controles iOS (UIDatePicker para definitivo) usam UITableViewCells internamente e quebram se você implementar isso em uma categoria.
Clafou
7
Este método parece não funcionar no iOS8 ao tentar remover uma célula no modo de edição. O setFrame é chamado quando você entra / sai do modo de edição para que a célula continue diminuindo. Alguma solução para isso?
John Baum,
3
@JohnBaum isso pode ajudar (pelo menos no meu caso funciona): stackoverflow.com/questions/25911484/ios-8-cell-resizing/…
HashtagMarkus
2
Esta solução é realmente uma dádiva de Deus. Caso alguém esteja se perguntando como fazer o mesmo em swift - reddit.com/r/swift/comments/2fr849/…
sysuser
16

Para fazer isso no Swift, que não fornece métodos para definir variáveis, você terá que substituir o setter para frame. Postado originalmente (pelo menos onde o encontrei) aqui

override var frame: CGRect {
    get {
        return super.frame
    }
    set (newFrame) {
        let inset: CGFloat = 15
        var frame = newFrame
        frame.origin.x += inset
        frame.size.width -= 2 * inset
        super.frame = frame
    }
}
JuJoDi
fonte
Trabalha para a Swift
Simon McNeil
9

Se nada funcionar, você pode tentar isso

Torne a cor de fundo da célula uma cor clara e coloque uma imagem da célula com o tamanho necessário. Se você quiser exibir algum texto nessa célula, coloque um rótulo acima da imagem. Não se esqueça de definir a cor de fundo do rótulo também para cor clara.

me inclua
fonte
8

Descobri que a solução aceita não funcionou na rotação. Para alcançar UITableViewCells com larguras fixas e margens flexíveis, apenas adaptei a solução acima para o seguinte:

- (void)setFrame:(CGRect)frame {

    if (self.superview) {
        float cellWidth = 500.0;
        frame.origin.x = (self.superview.frame.size.width - cellWidth) / 2;
        frame.size.width = cellWidth;
    }

    [super setFrame:frame];
}

O método é chamado sempre que o dispositivo gira, então as células estarão sempre centralizadas.

Graham
fonte
0

Existe um método que é chamado quando a tela é girada: viewWillTransitionToSize

É aqui que você deve redimensionar o quadro. Consultar exemplo. Altere as coordenadas do quadro conforme necessário.

- (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator
{
    [coordinator animateAlongsideTransition:nil completion:^(id<UIViewControllerTransitionCoordinatorContext> context)
    {
        int x = 0;
        int y = 0;
        self.tableView.frame = CGRectMake(x, y, 320, self.tableView.frame.size.height);
    }];
}
Cara
fonte
-2

eu faço isso em

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell;
    CGFloat tableBorderLeft = self.view.frame.origin.x + 10;
    CGFloat tableBorderRight = self.view.frame.size.width - 20;

    CGRect tableRect = self.view.frame;
    tableRect.origin.x = tableBorderLeft; 
    tableRect.size.width = tableBorderRight; 
    tableView.frame = tableRect;
}

E isso funcionou para mim

Lều Đức Quý
fonte
-6

No arquivo .h, adicione o delegado 'UITableViewDataSource'

-(CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{ 
    return size;
}
bharath gangupalli
fonte
4
Ele quer definir a largura, não a altura
Christopher Pickslay
oh hoo. sry pelo inconveniente.
bharath gangupalli
Você entendeu mal a pergunta e você respondeu pela altura e você sabe o que está funcionando para mim, porque eu estou procurando por altura e não por largura. Obrigado pela resposta
Pooja