ios - constraint - uistackview with scrollview




Tamanho do Conteúdo Scrollable do UIScrollView Ambiguidade (17)

Fellow devs, estou tendo problemas com o AutoLayout no Interface Builder (Xcode 5 / iOS 7). É muito básico e importante, então acho que todos deveriam saber como isso funciona corretamente. Se isso é um bug no Xcode, é um problema crítico!

Então, sempre que tenho uma hierarquia de visões como essa, me deparo com problemas:

>UIViewController
>> UIView
>>>UIScrollView
>>>>UILabel (or any other comparable UIKit Element)

O UIScrollView tem restrições sólidas, por exemplo, 50 px de todos os lados (sem problemas). Então eu adiciono uma restrição de Top Space ao UILabel (não há problema) (e posso até fixar a altura / largura do rótulo, nada muda, mas deve ser desnecessário devido ao tamanho intrínseco do Label)

O problema começa quando eu adiciono uma restrição à UILabel:

Por exemplo, Espaço à Vista: Superview Equals: 25

Agora dois avisos ocorrem - e não entendo o porquê:

A) Tamanho do Conteúdo Scrollable Ambiguidade (Scroll View possui altura / largura de conteúdo rolável ambíguos)

B) Exibições extraviado (Rótulo esperado: x = -67 real: x = 207

Eu fiz este exemplo mínimo em um novo projeto que você pode baixar e eu anexei uma captura de tela. Como você pode ver, o Interface Builder espera que o Label fique fora do limite do UIScrollView (o retângulo tracejado laranja). A atualização do quadro do Rótulo com a Ferramenta Resolver Problemas move-o para lá.

Observe: Se você substituir o UIScrollView por um UIView, o comportamento é o esperado (o quadro do Rótulo está correto e de acordo com a restrição). Portanto, parece haver um problema com o UIScrollView ou estou perdendo algo importante.

Quando eu executo o aplicativo sem atualizar o quadro do Rótulo como sugerido pela IB, ele está posicionado perfeitamente, exatamente onde deveria estar e o UIScrollView pode ser rolado. Se eu atualizar o quadro, o rótulo está fora de vista e o UIScrollView não rola.

Ajude-me Obi-Wan Kenobi! Por que o layout ambíguo? Por que a visão fora de lugar?

Você pode baixar o projeto de exemplo aqui e tentar se você pode descobrir o que está acontecendo: https://github.com/Wirsing84/AutoLayoutProblem


Você só precisa ter certeza de que existe uma maneira de fazer uma linha contínua de restrições do topo para a base da rolagem. [-XXX]

No meu caso - uma visualização de rolagem de rolagem horizontal - eu também precisava adicionar restrições de largura e altura para cada filho da visualização de rolagem, embora a nota técnica da Apple não lhe diga isso.


É a resposta para a minha pergunta auto-respondida UIScrollView + Centered View + Tamanho Ambigous Scrollable Content + muitos tamanhos de iPhone .

Mas cubra completamente o seu caso também!

Então, aqui está o estado inicial para o caso mais simples:

  1. scrollView com 0 restrições para todas as arestas
  2. Botão centralizado horizontal e vertical com restrições fixas de largura e altura
  3. E, claro - avisos irritantes Has ambiguous scrollable content width e Has ambiguous scrollable content height .

Tudo o que precisamos fazer é:

  • Adicione 2 restrições adicionais, por exemplo, "0" para trailing e / ou espaço inferior para a nossa visão (veja o exemplo na imagem abaixo).

Importante: você precisa adicionar restrições à direita e / ou inferiores . Não "líder e superior" - não funciona!

Você pode verificar isso no meu projeto de exemplo , que demonstra como corrigir esse problema.

PS

Segundo a lógica - essa ação deve causar "restrições conflitantes". Mas não!

Eu não sei porque funciona e como o Xcode detecta qual restrição é mais priorizada (porque eu não estou definido prioridade para essas restrições explicitamente). Ficarei grato se alguém explicar, por que funciona nos comentários abaixo.


Abordagem Swift 4+:

1) Defina as margens superior, inferior, esquerda e direita do UIScrollView como 0

2) Dentro do UIScrollView, adicione um UIView e configure as margens superior, inferior, inicial e final para 0 (igual às margens do UIScrollView).

3) A parte mais importante é definir largura e altura, onde a restrição de altura deve ter baixa prioridade .

private func setupConstraints() {
    // Constraints for scrollView
    scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
    scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
    scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
    scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
    // Constraints for containerView
    containerView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
    containerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
    containerView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
    containerView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
    containerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
    let heightConstraint = containerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor)
    heightConstraint.priority = UILayoutPriority(rawValue: 250)
    heightConstraint.isActive = true
}

As pessoas que estão lutando com uiscrollview não rolando apenas definem a restrição inferior da sua visualização de conteúdo com o layout inferior da última visualização (que está dentro da sua visualização de conteúdo). Não se esqueça de remover a restrição do centro Y.

Rest todas as restrições são as mesmas definidas acima. Scrollview apenas preocupou-se em obter a altura máxima de sua visualização de conteúdo, e estamos configurando-a como a restrição inferior da última visualização, o que significa que a rolagem automaticamente mudará seu deslocamento de conteúdo.

No meu caso, a última visualização foi UILable sem nenhuma propriedade de linhas = 0 (que ajusta automaticamente sua altura dependendo de seu conteúdo) para aumentar dinamicamente a altura de uilable e, eventualmente, aumentar a área rolável, pois o layout inferior de uilable está alinhado com a parte inferior da visualização de conteúdo que força o scrollview a aumentar seu deslocamento de conteúdo.


Conforme mencionado nas respostas anteriores, você deve adicionar uma visualização personalizada dentro da exibição de rolagem:

Adicione todas as suas subvisualizações à visualização de conteúdo. Em algum momento você verá uma visualização de conteúdo de rolagem com aviso de tamanho de conteúdo ambíguo, você deve selecionar a visualização de conteúdo e clicar no botão "Solucionar problemas de layout automático" (no canto inferior direito do layout IB) e selecionar "Adicionar ausente". restrições "opção.

De agora em diante, quando você executar o projeto, a visualização de rolagem atualizará automaticamente o tamanho do conteúdo, sem necessidade de código adicional.



Eu acho que é um trabalho de 10 segundos a partir de agora. Eu observei isso no XCode 7.3 e fiz um vídeo sobre ele. Verifique aqui:

https://www.youtube.com/watch?v=yETZKqdaPiI

Tudo o que você precisa fazer é adicionar uma subvisualização ao UIScrollView com a mesma largura e altura. Em seguida, selecione ViewController e pressione Reset to suggested constraint . Por favor, verifique o vídeo para uma compreensão clara.

obrigado


Eu estava recebendo o mesmo erro .. eu fiz o seguinte

  1. Visualizar (Superview)
  2. ScrollView 0,0,600,600
  3. UIView dentro de ScrollView: 0,0,600,600
  4. UIView contém visualização de imagem, rótulo

Agora adicione leading / trailing / top / bottom para scrollView (2) e depois UIView (3).

Selecione View (1) e View (3), definindo igualmente a altura e o peso. Foi solucionado meu problema.

Eu fiz o vídeo que vai ajudar:

https://www.youtube.com/watch?v=s-CPN3xZS1A


Eu fiz um vídeo no youTube
Scroll StackViews usando apenas Storyboard no Xcode

Eu acho que dois tipos de cenários podem aparecer aqui.

A visão dentro do scrollView -

  1. não tem conteúdo intrínseco Tamanho (por exemplo, UIView )
  2. tem seu próprio tamanho de conteúdo intrínseco (por exemplo, UIStackView )

Para uma visualização rolável verticalmente em ambos os casos, você precisa adicionar essas restrições:

  1. 4 restrições de cima, esquerda, inferior e direita.

  2. Largura igual à vista de rolagem (para parar de rolar horizontalmente)

Você não precisa de nenhuma outra restrição para visualizações que tenham sua própria altura de conteúdo intrínseco.


Para vistas que não possuem qualquer altura de conteúdo intrínseco, você precisa adicionar uma restrição de altura. A exibição rolará somente se a restrição de altura for maior que a altura da rolagemView.


Eu resolvi esse tipo de problema para o meu ponto de vista usando "Resolver problemas de layout automático"> "Adicionar restrições ausentes" para a exibição selecionada

As duas restrições a seguir resolvem meu problema:

trailing = Stack View.trailing - 10
bottom = Stack View.bottom + 76

em que: trailing, bottom são o trailing, bottom do UIScrollView


O que fiz foi criar uma visualização de conteúdo separada, conforme mostrado aqui.

A visualização de conteúdo é de forma livre e pode incluir todas as subvisualizações com suas próprias restrições em relação ao contentView.

O UIScrollView é adicionado ao controlador de exibição principal.

Programaticamente eu adiciono o contentView que está linkado via IBOutlet para classe e defino o contentView do UIScrollView.


Para mim, adicionar um contentView não funcionou como sugerido. Além disso, cria uma sobrecarga devido à visão adicionada (embora eu não considere isso um grande problema). O que funcionou melhor para mim foi apenas desligar a verificação de ambigüidade do meu scrollView . Tudo está bem, então acho que está tudo bem em casos simples como o meu. Mas tenha em mente que, se outras restrições para sua quebra scrollView , o Interface-Builder não irá avisá-lo mais sobre isso.


Usando o contentView ( UView ) como contêiner dentro do UIScrollView , UView bordas ( top , bottom , trailing , leading ) do superview ( UIScrollView ) e o contentView deve ter equalwidth e equalheight à superview. Essas são restrições. E chamada de método:

-(void)viewDidLayoutSubviews
{
    [super viewDidLayoutSubviews];
    self.scrollView.contentSize = self.contentView.frame.size;
}

Resolvi problemas para mim.


Veja abaixo: visualização de conteúdo em scrollview vertical e horizontal centralizado. você tem erro de ambigüidade, sempre certifique-se de que dois adicionados ao scrollview da sua visualização de conteúdo sejam 1) .button espaço para container.2) espaço à restrição que é destacada na captura de tela,

esses meios de restrição em pergaminho são quanto você pode rolar após a altura ou largura da exibição do conteúdo.

isso pode te ajudar.


[testado no XCode 7.2 e no iOS 9.2]

O que suprimiu os erros e avisos do Storyboard para mim foi definir o tamanho intrínseco da visualização de rolagem e da visualização de conteúdo (no meu caso, uma visualização de pilha) para o Espaço Reservado. Essa configuração é encontrada no Inspetor de tamanho no Storyboard. E diz: Definir um tamanho de conteúdo intrínseco de tempo de design afeta apenas uma exibição durante a edição no Interface Builder. A visualização não terá esse tamanho de conteúdo intrínseco em tempo de execução.

Então, acho que não estamos errando ao definir isso.

Nota: No storyboard, fixei todas as arestas da scrollview na superview e em todas as arestas da stackview para a scrollview. No meu código, configurei o translatesAutoresizingMaskIntoConstraints como false para o scrollview e o stackview. E eu não mencionei o tamanho do conteúdo. Quando o stackview cresce dinamicamente, as restrições definidas no storyboard garantem que a pilha seja rolável.

O aviso do storyboard estava me enlouquecendo e eu não queria centrar as coisas horizontalmente ou verticalmente apenas para suprimir o aviso.


todas as subvisualizações dentro de uma scrollview devem ter restrições tocando em todas as arestas da visualização de rolagem, como é explicado na documentação, a altura e a largura de uma visualização de rolagem são calculadas automaticamente pelas medidas das subvisualizações, isso significa que você precisa Trailing e principais restrições para largura e restrições Top e Bottom para altura.


iOS 12, Swift 4

A maneira mais simples de usar o autolayout :

  1. Adicione o UIScrollView e fixe-o 0,0,0,0 em superview (ou no tamanho desejado)
  2. Adicione o UIView no ScrollView, fixe-o 0,0,0,0 em todos os 4 lados e centralize-o na horizontally e na vertically .
  3. No inspetor de tamanho, altere a bottom e align center Y prioridade do align center Y para 250. (para a mudança de rolagem horizontal e align center X )
  4. Adicione todas as visualizações necessárias a essa exibição. Não se esqueça de definir a restrição inferior na visualização mais baixa.




interface-builder