Como quebrar texto em um UITableViewCell sem uma célula personalizada

151

Isso está no iPhone 0S 2.0. As respostas para 2.1 também são boas, embora eu não conheça nenhuma diferença em relação às tabelas.

Parece que deve ser possível agrupar o texto sem criar uma célula personalizada, pois a UITableViewCellcontém um UILabelpor padrão. Sei que posso fazê-lo funcionar se criar uma célula personalizada, mas não é isso que estou tentando alcançar - quero entender por que minha abordagem atual não funciona.

Eu descobri que o rótulo é criado sob demanda (uma vez que a célula suporta acesso a texto e imagem, por isso não cria a visualização de dados até que seja necessário), por isso, se eu fizer algo assim:

cell.text = @""; // create the label
UILabel* label = (UILabel*)[[cell.contentView subviews] objectAtIndex:0];

então eu recebo um rótulo válido, mas a configuração dele numberOfLines(e lineBreakMode) não funciona - ainda recebo texto de linha única. Há muita altura no UILabeltexto a ser exibido - estou retornando um grande valor para a altura em heightForRowAtIndexPath.

Airsource Ltd
fonte

Respostas:

277

Aqui está uma maneira mais simples e funciona para mim:

Dentro da sua cellForRowAtIndexPath:função. A primeira vez que você cria seu celular:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
    cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
    cell.textLabel.numberOfLines = 0;
    cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:17.0];
}

Você notará que eu defino o número de linhas do rótulo como 0. Isso permite usar quantas linhas forem necessárias.

A próxima parte é especificar o tamanho que você UITableViewCellterá, e faça isso em sua heightForRowAtIndexPathfunção:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellText = @"Go get some text for your cell.";
    UIFont *cellFont = [UIFont fontWithName:@"Helvetica" size:17.0];
    CGSize constraintSize = CGSizeMake(280.0f, MAXFLOAT);
    CGSize labelSize = [cellText sizeWithFont:cellFont constrainedToSize:constraintSize lineBreakMode:UILineBreakModeWordWrap];

    return labelSize.height + 20;
}

Adicionei 20 à altura da célula retornada porque gosto de um pequeno buffer em torno do meu texto.

Tim Rupe
fonte
17
Você não precisa definir seu cell.textLabel.numberOfLines como um número arbitrariamente alto. Configurá-lo como 0 significa "quantas linhas forem necessárias para exibir".
mmc
Obrigado, vou editar minha postagem hoje à noite depois de ter a chance de verificá-la em meu próprio projeto.
Tim Rupe
1
Definir número de linhas para 0 funciona bem (como muitas linhas como é preciso para exibição)
Prakash
1
cagreen: Acontece que eu posso replicar isso, mas somente se eu usar o iPhone OS 3.0 no simulador. Quando uso o 3.1+, o redimensionamento do detailTextLabel corresponde ao de sizeWithFont. Portanto, o método de Tim funciona muito bem - apenas para o 3.1+ (provavelmente devido a um erro / falha na renderização padrão da célula 3.0). Para o registro, eu estou usando uma margem vertical superior / inferior de 12 (cada), um tamanho de etiqueta detalhes texto (188,0, CGFLOAT_MAX), e um boldSystemFontOfSize 15.
Joe D'Andrea
17
UILineBreakModeWordWrap está obsoleto no iOS 6. Use NSLineBreakByWordWrapping.
Ethan Allen
16

Atualização da resposta de Tim Rupe para iOS7:

UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] ;
    cell.textLabel.lineBreakMode = NSLineBreakByWordWrapping;
    cell.textLabel.numberOfLines = 0;
    cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:17.0];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSString *cellText = @"Go get some text for your cell.";
    UIFont *cellFont = [UIFont fontWithName:@"Helvetica" size:17.0];

    NSAttributedString *attributedText =
        [[NSAttributedString alloc]
            initWithString:cellText
            attributes:@
            {
                NSFontAttributeName: cellFont
            }];
    CGRect rect = [attributedText boundingRectWithSize:CGSizeMake(tableView.bounds.size.width, CGFLOAT_MAX)
                                               options:NSStringDrawingUsesLineFragmentOrigin
                                               context:nil];
    return rect.size.height + 20;
}
ddiego
fonte
3

Um breve comentário / resposta para registrar minha experiência quando tive o mesmo problema. Apesar de usar os exemplos de código, a altura da célula da exibição de tabela estava se ajustando, mas o rótulo dentro da célula ainda não estava se ajustando corretamente - a solução era carregar a minha célula a partir de um arquivo NIB personalizado, o que ocorre após o ajuste da altura da célula.

E eu tinha minhas configurações dentro do arquivo NIB para não quebrar o texto e só tinha 1 linha para o rótulo; as configurações do arquivo NIB estavam substituindo as configurações que eu ajustei dentro do código.

A lição que tomei foi a de ter sempre em mente o estado dos objetos em cada momento - eles podem não ter sido criados ainda! ... alguém na fila.

Richard Le Mesurier
fonte
2

Se quisermos adicionar apenas texto na UITableViewcélula, precisamos apenas de dois delegados para trabalhar (não é necessário adicionar mais UILabels)

1) cellForRowAtIndexPath

2) heightForRowAtIndexPath

Esta solução funcionou para mim: -

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{ 
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:16];
    cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
    cell.textLabel.numberOfLines = 0;

    [cell setSelectionStyle:UITableViewCellSelectionStyleGray]; 
    cell.textLabel.text = [mutArr objectAtIndex:indexPath.section];
    NSLog(@"%@",cell.textLabel.text);

    cell.accessoryView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"arrow.png" ]];

    return cell;

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{  
    CGSize labelSize = CGSizeMake(200.0, 20.0);

    NSString *strTemp = [mutArr objectAtIndex:indexPath.section];

    if ([strTemp length] > 0)
        labelSize = [strTemp sizeWithFont: [UIFont boldSystemFontOfSize: 14.0] constrainedToSize: CGSizeMake(labelSize.width, 1000) lineBreakMode: UILineBreakModeWordWrap];

    return (labelSize.height + 10);
}

Aqui a string mutArré uma matriz mutável da qual estou recebendo meus dados.

EDIT: - Aqui está a matriz que eu peguei.

mutArr= [[NSMutableArray alloc] init];

[mutArr addObject:@"HEMAN"];
[mutArr addObject:@"SUPERMAN"];
[mutArr addObject:@"Is SUPERMAN powerful than HEMAN"];
[mutArr addObject:@"Well, if HEMAN is weaker than SUPERMAN, both are friends and we will never get to know who is more powerful than whom because they will never have a fight among them"];
[mutArr addObject:@"Where are BATMAN and SPIDERMAN"];
Arshad Parwez
fonte
2

Agora, as visualizações de tablaturas podem ter células de auto-dimensionamento. Defina a visualização da tabela da seguinte maneira

tableView.estimatedRowHeight = 85.0 //use an appropriate estimate tableView.rowHeight = UITableViewAutomaticDimension

Referência Apple

Jason
fonte
0

Eu uso as seguintes soluções.

Os dados são fornecidos separadamente em um membro:

-(NSString *)getHeaderData:(int)theSection {
    ...
    return rowText;
}

O manuseio pode ser feito facilmente cellForRowAtIndexPath. Defina a célula / defina a fonte e atribua esses valores ao resultado "célula". Observe que numberoflinesestá definido como "0", o que significa pegar o que é necessário.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    UIFont *cellFont = [UIFont fontWithName:@"Verdana" size:12.0];
    cell.textLabel.text= [self getRowData:indexPath.section];
    cell.textLabel.font = cellFont;
    cell.textLabel.numberOfLines=0;
    return cell;
}

Em heightForRowAtIndexPath, calculo as alturas do texto agrupado. O tamanho do código deve estar relacionado à largura da sua célula. Para o iPad, esse valor deve ser 1024. Para o iPhone e iPod 320.

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UIFont *cellFont = [UIFont fontWithName:@"Verdana" size:12.0];
    CGSize boundingSize = CGSizeMake(1024, CGFLOAT_MAX);
    CGSize requiredSize = [[self getRowData:indexPath.section] sizeWithFont:cellFont constrainedToSize:boundingSize lineBreakMode:UILineBreakModeWordWrap];
    return requiredSize.height;    
}
Vincent
fonte
0

Achei isso muito simples e direto:

[self.tableView setRowHeight:whatEvereight.0f];

por exemplo:

[self.tableView setRowHeight:80.0f];

Essa pode ou não ser a melhor abordagem / padrão para isso, mas funcionou no meu caso.

Manish Kr. Shukla
fonte
Pelo que entendi, a propriedade rowHeight define uma altura fixa que será usada para todas as células na exibição de tabela. Usar rowHeight é melhor para o desempenho em tabelas grandes, mas se você precisar que a altura de cada célula varie com base em seu conteúdo, parece que o método tableView: heightForRowAtIndexPath: deve ser usado.
Jk7
0

Tente meu código rapidamente. Este código também funcionará para UILabels normais.

extension UILabel {
    func lblFunction() {
        //You can pass here all UILabel properties like Font, colour etc....
        numberOfLines = 0
        lineBreakMode = .byWordWrapping//If you want word wraping
        lineBreakMode = .byCharWrapping//If you want character wraping
    }
}

Agora ligue simplesmente assim

cell.textLabel.lblFunction()//Replace your label name 
iOS
fonte
-1

Eu acho que essa é uma solução melhor e mais curta. Apenas formate o UILabel( textLabel) da célula para calcular automaticamente a altura especificando sizeToFite tudo ficará bem.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil)
    {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
    }

    // Configure the cell...
    cell.textLabel.text = @"Whatever text you want to put here is ok";
    cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
    cell.textLabel.numberOfLines = 0;
    [cell.textLabel sizeToFit];

    return cell;
}
dukz
fonte
-2

Eu não acho que você pode manipular uma base UITableViewCell'sprivada UILabelpara fazer isso. Você pode adicionar um novo UILabelpara a célula-se e usar numberOfLinescom sizeToFita dimensioná-lo adequadamente. Algo como:

UILabel* label = [[UILabel alloc] initWithFrame:cell.frame];
label.numberOfLines = <...an appriate number of lines...>
label.text = <...your text...>
[label sizeToFit];
[cell addSubview:label];
[label release];
drewh
fonte