Eu projetei minha célula personalizada no IB, subclassifiquei-a e conectei minhas tomadas à minha classe personalizada. Eu tenho três subvisões no conteúdo da célula que são: UIView (cdView) e dois rótulos (titleLabel e emailLabel). Dependendo dos dados disponíveis para cada linha, às vezes quero exibir o UIView e dois rótulos na minha célula e, às vezes, apenas dois rótulos. O que estou tentando fazer é definir restrições dessa maneira, se eu definir a propriedade UIView como oculta ou removê-la da super visão, os dois rótulos serão movidos para a esquerda. Tentei definir a restrição principal do UIView como Superview (conteúdo da célula) para 10px e as restrições principais do UILiew para 10 px na próxima visualização (UIView). Mais tarde no meu código
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(IndexPath *)indexPath {
...
Record *record = [self.records objectAtIndex:indexPath.row];
if ([record.imageURL is equalToString:@""]) {
cell.cdView.hidden = YES;
}
Estou ocultando meu cell.cdView e gostaria que os rótulos se movessem para a esquerda, mas eles permanecem na mesma posição no Cell. Tentei remover cell.cdView da superview, mas também não funcionou. Anexei uma imagem para esclarecer o que sou.
Sei como fazer isso programaticamente e não estou procurando essa solução. O que eu quero é definir restrições no IB e espero que minhas subvisões sejam movidas dinamicamente se outras visualizações forem removidas ou ocultas. É possível fazer isso no IB com layout automático?
.....
fonte
Respostas:
É possível, mas você terá que fazer um pouco de trabalho extra. Existem algumas coisas conceituais para sair do caminho primeiro:
No seu caso, isso provavelmente significa:
O que você precisa fazer é restringir criteriosamente os rótulos. Deixe suas restrições existentes (10 pontos de espaço para a outra visualização), mas adicione outra restrição: faça as bordas esquerdas dos seus rótulos 10 pontos da borda esquerda da superview com uma prioridade não necessária (a alta prioridade padrão provavelmente funcionará bem).
Em seguida, quando você desejar que eles se movam para a esquerda, remova completamente a vista esquerda. A restrição obrigatória de 10 pontos à vista esquerda desaparecerá junto com a vista a que se refere, e você terá apenas uma restrição de alta prioridade de que os rótulos estejam a 10 pontos da visão geral. Na próxima passagem de layout, isso deve fazer com que eles se expandam para a esquerda até preencherem a largura da superview, exceto pelo espaçamento nas bordas.
Uma ressalva importante: se você quiser voltar à vista esquerda da imagem, não apenas precisará adicioná-la novamente à hierarquia da vista, mas também precisará restabelecer todas as restrições ao mesmo tempo. Isso significa que você precisa de uma maneira de colocar sua restrição de espaçamento de 10 pontos entre a exibição e seus rótulos sempre que essa exibição for exibida novamente.
fonte
|-(space)-[hidden(0)]-(space)-[visible]
é efetivamente|-(2*space)-[visible]
. Segundo, essa visualização pode começar a gerar violações de restrição, dependendo de sua própria subárvore e restrições de visualização - você não pode garantir que pode restringir arbitrariamente uma visualização na largura 0 e mantê-la funcionando.|-[otherViews]-[eitherThis][orThis]-|
:), mas acabei encontrando esse problema eventualmente.Adicionar ou remover restrições durante o tempo de execução é uma operação pesada que pode afetar o desempenho. No entanto, existe uma alternativa mais simples.
Para a vista que você deseja ocultar, configure uma restrição de largura. Restrinja as outras vistas com uma lacuna horizontal principal a essa vista.
Para ocultar, atualize a
.constant
restrição de largura para 0.f. As outras vistas se moverão automaticamente para a esquerda para assumir a posição.Veja minha outra resposta aqui para obter mais detalhes:
Como alterar as restrições de rótulo durante o tempo de execução?
fonte
Para aqueles que oferecem suporte apenas ao iOS 8 ou superior , há uma nova propriedade booleana ativa . Ajudará a habilitar apenas as restrições necessárias dinamicamente
A saída de restrição PS deve ser forte , não fraca
Exemplo:
Além disso, para corrigir um erro no storyboard, desmarque a caixa de
Installed
seleção de uma dessas restrições.UIStackView (iOS 9 ou superior)
Mais uma opção é agrupar suas visualizações
UIStackView
. Quando a vista estiver ocultaUIStackView
, o layout será atualizado automaticamentefonte
UIStackView
reposiciona suas visualizações automaticamente quando ahidden
propriedade é alterada em qualquer uma de suas subvisões (iOS 9+).Vá para 11:48 neste vídeo da WWDC para uma demonstração:
Mistérios do layout automático, parte 1
fonte
Meu projeto usa uma
@IBDesignable
subclasse personalizada deUILabel
(para garantir consistência em cores, fontes, inserções etc.) e implementei algo como o seguinte:Isso permite que a subclasse de etiqueta participe do Layout automático, mas não ocupa espaço quando oculta.
fonte
Para os Googlers: com base na resposta de Max, para resolver o problema do preenchimento que muitos notaram, simplesmente aumentei a altura do rótulo e usei essa altura como separador em vez do preenchimento real. Essa ideia pode ser expandida para qualquer cenário que contenha visualizações.
Aqui está um exemplo simples:
Nesse caso, mapeio a altura do rótulo do autor para um apropriado
IBOutlet
:e quando defino a altura da restrição
0.0f
, preservamos o "preenchimento", porque a altura do botão Reproduzir permite isso.fonte
NSLayoutConstraint
, acredito que você deseja atualizar aconstant
propriedade do seuauthorLabelHeight
.conecte a restrição entre a uiview e os rótulos como IBOutlet e configure o membro de prioridade com um valor menor quando configurado oculto = YES
fonte
O que acabei fazendo foi criar 2 xibs. Um com a vista esquerda e outro sem ela. Registrei o controlador e decidi qual usar durante cellForRowAtIndexPath.
Eles usam a mesma classe UITableViewCell. A desvantagem é que há alguma duplicação do conteúdo entre os xibs, mas essas células são bastante básicas. A vantagem é que não tenho um monte de código para gerenciar manualmente a remoção de exibição, atualização de restrições etc.
Em geral, essa provavelmente é uma solução melhor, pois são layouts tecnicamente diferentes e, portanto, devem ter xibs diferentes.
fonte
Nesse caso, mapeio a altura do rótulo do autor para um IBOutlet apropriado:
e quando defino a altura da restrição como 0,0f, preservamos o "preenchimento", porque a altura do botão Reproduzir permite isso.
fonte
Use duas UIStackView Horizontal e Vertical, quando alguma subvisualização da pilha estiver oculta, outras subvisões da pilha serão movidas, use Distribuição -> Preencher proporcionalmente para a pilha vertical com dois UILabels e precisar definir consensos de largura e altura para o primeiro UIView
fonte
Tente isso, eu implementei o código abaixo,
Eu tenho uma View no ViewController na qual adicionamos outras três views. Quando alguma view estiver oculta, outras duas view se moverão, siga as etapas abaixo. ,
1.ViewController.h Arquivo
2.ViewController.m
Esperança Então, essa lógica ajudará alguém.
fonte
No meu caso, defino a constante da restrição de altura como
0.0f
e também ahidden
propriedadeYES
.Para mostrar a vista (com os subviews) mais uma vez eu fiz o contrário: eu definir a constante altura para um valor diferente de zero e defina a
hidden
propriedade paraNO
.fonte
Vou usar o stackview horizontal. Ele pode remover o quadro quando a subvisão está oculta.
Na imagem abaixo, a exibição em vermelho é o contêiner real do seu conteúdo e possui 10 pontos à direita da superview laranja (ShowHideView), basta conectar o ShowHideView ao IBOutlet e mostrar / ocultar / remover programaticamente.
fonte
Esta é minha outra solução usando restrição de prioridade. A ideia é definir a largura como 0.
crie uma visualização de contêiner (laranja) e defina a largura.
crie uma visualização de conteúdo (vermelho) e defina o espaço à direita 10pt para superview (laranja). Observe as restrições de espaço à direita, existem 2 restrições à direita com prioridade diferente. Baixo (= 10) e Alto (<= 10). Isso é importante para evitar ambiguidade.
Defina a largura da vista laranja como 0 para ocultar a vista.
fonte
Como no_scene sugeriu, você pode definitivamente fazer isso alterando a prioridade da restrição no tempo de execução. Isso foi muito mais fácil para mim, porque eu tinha mais de uma visão de bloqueio que precisaria ser removida.
Aqui está um trecho usando ReactiveCocoa:
fonte
Caso isso ajude alguém, criei uma classe auxiliar para usar restrições de formato visual . Estou usando no meu aplicativo atual.
AutolayoutHelper
Pode ser um pouco adaptado às minhas necessidades, mas você pode achar útil ou pode modificá-lo e criar seu próprio auxiliar.
Eu tenho que agradecer a Tim pela resposta acima , esta resposta sobre o UIScrollView e também este tutorial .
fonte
Aqui está como eu realinharia minhas uiviews para obter sua solução:
Eu criei minha própria regra de ouro. Sempre que você precisar ocultar / mostrar qualquer visão geral cujas restrições possam ser afetadas, adicione todas as subvisões afetadas / dependentes dentro de uma visão geral e atualize sua restrição principal / final / superior / inferior constante programaticamente.
fonte
Esta é uma pergunta antiga, mas ainda espero que ajude. Vindo do Android, nesta plataforma, você tem um método útil
isVisible
para ocultá-lo da visualização, mas também não considera o quadro quando o layout automático desenha a visualização.usando a extensão e a extensão "uiview", você pode executar uma função semelhante no ios (não sabe por que ela ainda não está no UIKit) aqui uma implementação no swift 3:
fonte
a maneira correta de fazer isso é desabilitar as restrições com isActive = false. observe, no entanto, que a desativação de uma restrição a remove e libera, portanto você precisa ter saídas fortes para elas.
fonte
A solução mais fácil é usar o UIStackView (horizontal). Adicionar à exibição de pilha: primeira exibição e segunda exibição com etiquetas. Em seguida, defina a propriedade isHidden da primeira visualização como false. Todas as restrições serão calculadas e atualizadas automaticamente.
fonte
Eu acho que essa é a resposta mais simples. Por favor, verifique se funciona:
verifique aqui https://www.youtube.com/watch?v=EBulMWMoFuw
fonte