ios - uitableviewdelegate - uitableviewcontroller swift example



Expanda UILabel dentro do UITableView com o botão "mais" como o Instagram (1)

Eu tenho um projeto (que foi escrito por outras pessoas) onde há um feed com conteúdo e texto exibido dentro de uma exibição de tabela. Cada postagem corresponde a uma seção na exibição de tabela e cada seção possui suas próprias linhas correspondentes a elementos como conteúdo, texto, botão etc.

Eu preciso exibir um rótulo curto para legendas de postagem com um botão "mais" dentro da célula de exibição de tabela e quando mais botão é tocado, o rótulo será expandido para qualquer tamanho a legenda se encaixa, tudo acontecendo dentro de uma célula de exibição de tabela. Quando o botão mais é tocado, mudo a propriedade numberOfLines do rótulo para zero e, como as células têm altura automática, tudo o que preciso é recarregar essa célula de legenda específica. (a célula é exibida corretamente com o tamanho expandido se eu definir numberOfLines como 0 no primeiro lugar antes de exibir a célula.)

Eu tentei:

[tableView beginUpdates]; tableView endUpdates];

Eu tentei várias opções de animação com:

[tableView reloadRowsAtIndexPaths:@[myPath] withRowAnimation:UITableViewRowAnimation(Bottom,Top,None etc)];

Eu tentei:

[tableView reloadSections:[NSIndexSet indexSetWithIndex:myPath.section] withRowAnimation:UITableViewRowAnimation(Top,Bottom,None etc)];

Mas todos produzem o mesmo resultado: todo o layout da visualização de tabela fica confuso: ele salta para outra célula, algumas exibições ficam em branco, as células se sobrepõem, o vídeo dentro das células pára de ser reproduzido e a etiqueta não se expande (mas é atualizada em si, por exemplo, que a visualização curta txt com uma linha anima de cima / baixo etc, mas não se expande).

O que pode estar causando a bagunça de toda a exibição de tabela e como posso recarregar apenas uma célula corretamente com a animação de expansão, sem bagunçar todo o layout? Eu vi muitas perguntas e respostas sobre isso, mas todas elas recomendam as opções que eu já tentei e expliquei acima.

Meu aplicativo segmenta o iOS 8.0+

ATUALIZAÇÃO: Aqui está o código relevante (com algumas partes relacionadas ao funcionamento interno que não estão relacionadas ao layout, removidas):

MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier: MyCellIdentifier forIndexPath:indexPath];
cell.delegate = self;
cell.indexPathToReloadOnAnimation = indexPath;
cell.shouldShortenCaption = YES;

id post = self.posts[indexPath.section] ;
[cell setPost:post];

return cell;

E dentro de setPost: ::

if(self.shouldShortenCaption){
    captionLabel.numberOfLines = 2;
}else{
    captionLabel.numberOfLines = 0;
}
NSString *text = [some calculated (deterministic) text from post object];

A ação do botão é simples:

self.shouldShortenCaption = NO;
[one of the reload codes that I've written above in the question]

UPDATE 2: Aqui estão mais alguns métodos sobre o assunto:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
    if (section < self.posts.count) {
        return 59;
    }else
        return 0;
}

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    if (section < self.posts.count) {
        MyFeedHeader *header = [tableView dequeueReusableCellWithIdentifier:MyFeedHeaderIdentifier];
        header.delegate = self;
        [header setPostIndex:section];
        [header setPost:self.posts[section]] ;

        return header;
    }
    else
        return nil;
}

O método setPost: basicamente define os textos relevantes para rótulos (que não têm nada a ver com a legenda, são células completamente diferentes. A célula problemática não é a célula de cabeçalho). A tabela não possui métodos de rodapé. O único método em relação à altura é o acima.

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if (section >= self.posts.count) {
        return 1;
    }
    id post = self.posts[section];
    [calculate number of rows, which is deterministic]
    return [number of rows];
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    BOOL hasCursor = self.cursor && self.hasMore ? 1 : 0;
    return self.posts.count + hasCursor;
}

(Pós contagem e cursor e hasMore também são determinísticos).

ATUALIZAÇÃO 3: Eu fiz uma pergunta (que não era uma duplicata, mesmo que houvesse perguntas similares) e obtive uma resposta útil que resolveu meu problema. Os downvoters podem, por favor, explicar o motivo de terem downvoted?


Aqui está um exemplo: https://github.com/DonMag/DynamicCellHeight

A Tabela B é uma maneira de realizar "Mais / Menos" (a Tabela A foi para outro layout com o qual eu brinquei). Ele usa o [tableView beginUpdates]; tableView endUpdates]; [tableView beginUpdates]; tableView endUpdates]; método de desencadear o re-layout da tabela.

A chave é obter todas as suas restrições configuradas corretamente, para que o mecanismo de layout automático faça o que você espera.

O exemplo está em Swift, mas deve ser facilmente traduzido de volta para Obj-C (acho que fiz isso em Obj-C primeiro).

Editar: algumas notas adicionais ...

Isso está usando um método bastante padrão de células de exibição de tabela de altura dinâmica. As restrições de espaçamento vertical entre os elementos efetivamente "empurram" os limites da célula. O toque aqui alterna a propriedade numberOfLines do rótulo entre 2 e 0 (zero significa quantas linhas forem necessárias). Chamadas sequenciais para beginUpdates / endUpdates na exibição de tabela informam ao mecanismo de layout automático para recalcular as alturas de linha sem precisar recarregar os dados.

Para este exemplo, usei um pequeno "truque" para obter o efeito suave de expansão / colapso ... O rótulo de clipsToBounds você vê aqui está contido em um UIView (com clipsToBounds true). Há um segundo rótulo duplicado de múltiplas linhas (alfa 0, portanto não visível) que controla a altura. Descobri que mudar o numberOfLines no tipo de rótulo visível de "snapped" para 2 linhas e, em seguida, a animação de mudança de tamanho ocorreu ... resultando no texto "pulando".

Só por isso, eu adicionei a versão "não tão boa" ao meu repositório do GitHub para comparação.





uitableviewautomaticdimension