Passei dois dias testando as várias soluções para abordagens de Autolayout misto e puro para obter o que era uma configuração trivial de scrollview antes do autolayout, e agora é oficial - devo ser muito estúpido. Estou configurando isso principalmente no Storyboard (bem, é do jeito que está).
Então aqui está o meu pedido de ajuda.
Viewtree:
UIView
-UIView
-UIView
..-UIScrollview
...-UIButton
...-UIButton
...-UIButton
Os botões devem rolar horizontalmente (da esquerda para a direita e vice-versa). Alguém pode por favor deixe-me saber como definir as limitações para alcançar este objectivo usando puro AutoLayout ???
-
Eu tentei a abordagem mista, assim:
UIView
- UIView
- UIView
..-UIScrollview
...-UIView (contentview)
....-UIButton
....-UIButton
....-UIButton
... e definir restrições fixas de largura e altura para contentview
as translatesAutoresizingMaskIntoConstraints
configurações e de acordo com a Nota técnica da Apple. Os botões e a visualização de rolagem são configurados usando restrições. Isso obtém a rolagem do scrollview (yay), mas, infelizmente, ele rola muito longe! Tanto quanto eu posso dizer, a largura da rolagem é de alguma forma duplicada do que eu defini a visualização do conteúdo em ??? !!!
Tentei também a abordagem de autolayout puro, com contentview
e sem. Todas as visualizações são translatesAutoresizingMaskIntoConstraints=NO
, exceto self.view
. Os botões têm restrições fixas de largura / altura e são fixados nas quatro arestas da visualização de rolagem. Nada rola.
Por isso, estou totalmente perplexo porque não consigo fazê-lo funcionar corretamente. Qualquer ajuda é muito apreciada, e se você precisar de outras informações, pergunte!
ATUALIZADO Screenshot com solução - restrições buttonZ:
EDIT @ Jamie Forrest Portanto, a solução acaba sendo a restrição à direita no último botão. Em vez de 6441, o valor que eu havia definido era negativo, -6441. O mais complicado é que, ao definir o valor no storyboard, há duas opções na barra de ferramentas Pin:
O valor atual da tela é negativo (levando a nenhuma rolagem), e a opção abaixo é positiva (ativação da rolagem). Isso significa que eu não sou estúpido, mas pelo menos meio cego, eu acho. Embora, em minha defesa, não seja um pouco perturbador o fato de o XCode não mostrar um erro para a configuração "incorreta"?
EDITADO NOVAMENTE Agora, isso é engraçado ... alterar o valor à direita de -6441 (sem rolagem) para 6441 rolagem ativada. Mas meu velho amigo, o "muito conteúdo" estava de volta, levando a um tamanho de conteúdo duas vezes maior do que deveria ser! A solução para obter a rolagem correta do conteúdo foi definir a restrição à direita como ZERO! Isso não é óbvio ao trabalhar no Storyboard, mas ao olhar para o código do @Infinity James, é o que deveria ser.
fonte
contentSize
um deUIScrollView
apenas usando o layout automático. E é issocontentSize
que define quanto você pode rolar. Então, você precisará definir isso manualmente em algum lugar eventualmente. De resto, você pode usar restrições de layout para configurar os quadros de vista um em relação ao outro.Respostas:
É difícil ver os valores exatos e a configuração de suas restrições conforme você as colou aqui, por isso não tenho certeza de olhar para as capturas de tela onde você errou.
Em vez de explicar o que está errado na sua configuração, criei um projeto de amostra básico com uma hierarquia de exibição e restrição de exibição muito semelhante à que você descreve. A rolagem horizontal funciona conforme o esperado no projeto de exemplo, que usa a abordagem "Pure AutoLayout" descrita pela Apple na Nota técnica .
Também tive muitos problemas para conseguir o Auto Layout para trabalhar
UIScrollView
. A chave para fazê-lo funcionar é garantir que todos os itens da exibição de rolagem, juntos, tenham restrições que eventualmente se vinculem a todos os lados da exibição de rolagem e que contribuam para que o sistema AutoLayout possa determinar um contentSize para o exibição de rolagem que será maior que seu quadro. Parece que você estava tentando fazer isso no seu código, mas talvez houvesse algumas restrições supérfluas que estavam tornando o contentSize muito pequeno.Além disso, como outros mencionados, com AutoLayout e UIScrollview, você não define mais o contentSize explicitamente. O sistema de AutoLayout calcula o contentSize com base em suas restrições.
Também achei este capítulo de e-book muito útil para me fazer entender como tudo isso funciona. Espero que tudo isso ajude.
fonte
LOL bem-vindo ao clube da estupidez. Eu sou um dos fundadores. : D
Para rolagem VERTICAL : a única maneira de fazê-lo funcionar (iOS 8, Xcode 6 e autolayout puro) era adicionar as seguintes restrições à minha Visualização de rolagem (todas relacionadas à superview):
Minha estrutura:
Esse é o resultado final:
Esta é a configuração:
Tela cheia
Felizmente, isso salvaria alguém de DORMIR às 5 da manhã. : D
fonte
Exemplo autônomo simples
A julgar pelo alto número de votos na pergunta e pelo baixo número de votos nas respostas, as pessoas não encontram aqui uma solução rápida e compreensível. Deixe-me tentar adicionar um. Este projeto é um exemplo independente feito completamente no Interface Builder. Você deve poder trabalhar com ele em 10 minutos ou menos. Em seguida, você pode aplicar os conceitos que aprendeu ao seu próprio projeto.
A pergunta original pergunta sobre os botões de rolagem. Aqui eu apenas uso
UIView
s, mas eles podem representar a visualização que você quiser. Também escolhi a rolagem horizontal porque as capturas de tela do storyboard são mais compactas para este formato. Os princípios são os mesmos para a rolagem vertical, no entanto.Conceitos chave
UIScrollView
deve usar apenas uma subvisão. Este é um 'UIView' que serve como visualização de conteúdo para armazenar tudo o que você deseja rolar.Iniciar um novo projeto
Pode ser apenas um aplicativo de visualização única.
Storyboard
Neste exemplo, faremos uma visualização de rolagem horizontal. Selecione o View Controller e, em seguida, escolha Freeform no Size Inspector. Faça a largura
1,000
e a altura300
. Isso nos dá espaço no storyboard para adicionar conteúdo que será rolado.Adicionar uma visualização de rolagem
Adicione um
UIScrollView
e fixe todos os quatro lados à visualização raiz do controlador de visualização.Adicionar uma visualização de conteúdo
Adicione a
UIView
como uma subview à exibição de rolagem. Isso é fundamental. Não tente adicionar muitas subvisões à exibição de rolagem. Basta adicionar um únicoUIView
. Essa será sua visualização de conteúdo para as outras visualizações que você deseja rolar. Coloque a visualização de conteúdo na visualização de rolagem nos quatro lados.Equal Heights
Agora, no Resumo do documento, Commandclique na exibição de conteúdo e na exibição pai da exibição de rolagem para selecionar os dois. Em seguida, defina as alturas como iguais ( Controlarraste da Visualização de conteúdo para a Visualização de rolagem). Isso também é fundamental. Como estamos rolando horizontalmente, a exibição do conteúdo da visualização de rolagem não saberá quão alto deve ser, a menos que a definamos dessa maneira.
Nota:
Adicionar conteúdo
Adicione três se
UIView
dê todas as restrições. Eu usei margens de 8 pontos para tudo.Restrições:
Definir as restrições de largura também é essencial para que a visualização de rolagem saiba qual será a largura da visualização de conteúdo.
Acabado
Isso é tudo. Você pode executar seu projeto agora. Ele deve se comportar como a imagem de rolagem na parte superior desta resposta.
Para rolagem vertical, basta trocar todas as direções de largura e altura neste exemplo (testado e funcionando).
Um estudo mais aprofundado
fonte
O contentSize é definido implicitamente aplicando as restrições dentro do UIScrollView.
Por exemplo, se você tem um UIScrollView dentro de um UIView, ele ficará assim (como eu tenho certeza que você sabe):
Isso definirá o scrollView para preencher o tamanho do containerView (para que o containerView precise ter um determinado tamanho).
Em seguida, você pode ajustar o contentSize do UIScrollView configurando-o implicitamente para ser grande o suficiente para manter os botões como este:
fonte
Existem muitas perguntas sobre o uso do AutoLayout com o UIScrollView, o ponto principal que ignoramos é que as visualizações internas do UIScrollView fazem restrições contra a Visualização de conteúdo, mas não o próprio UIScrollView. Consulte a Nota técnica TN2154 , você pode encontrar:
A figura a seguir mostra que:
Você pode descobrir que o espaço à direita é de 500 pontos; se a restrição for feita no UIScrollView, a visualização será perdida e deve ser atualizada seu quadro. No entanto, sem avisos e sem erros. Porque todas as restrições são contra a exibição do conteúdo.
O UIScrollView calculará o tamanho da visualização do conteúdo de acordo com as restrições das visualizações internas. (Por exemplo, o tamanho do conteúdo: width = 100 (espaço à esquerda) + 200 (largura da visualização) + 500 (espaço à direita), altura = 131 (espaçamento superior) + 200 (altura) + 269 (espaçamento inferior)
Como adicionar restrições para visualizações no UIScrollView:
E tudo está feito.
Uma maneira fácil de lidar com o AutoLayout com scrollview é adicionar uma exibição de contêiner contendo todas as subvisões na exibição de rolagem.
Conclusão: o ponto principal para entender o AutoLayout com o UIScrollView é que as visualizações internas fazem restrições à exibição de conteúdo, mas não o próprio UIScrollView.
código de exemplo anexado
fonte
A seguinte solução funcionou para mim no scrollView com autolayout e sem contentSize :
E você terminou. Agora, você pode adicionar qualquer número de controles a essa exibição e aplicar as restrições relevantes uma para a outra (que não parecem funcionar sem essa exibição). Se você não quiser usar essa exibição, precisará aplicar restrições para cada controle relacionado ao scrollView (não relacionado um ao outro).
A dica esmagadora ..............
Crítico . Digamos, com clareza, que o UIScrollView tem 1000 de largura e 100 de altura. (De fato, normalmente esses valores seriam dinâmicos, é claro, dependendo da largura do dispositivo, etc. Mas, por enquanto, basta dizer 1000 de largura e 100 de altura.) Digamos que você esteja fazendo uma rolagem horizontal. Então coloque uma UIView dentro do UIScrollView. (Essa é a "exibição de conteúdo".) Defina todas as quatro restrições da exibição de conteúdo superior, inferior, inicial, final, para a exibição de rolagem. Faça todos zero, mesmo que isso pareça errado. Defina a altura do conteúdo do UIView como 100 e esqueça isso. Agora: você deseja rolar horizontalmente, então defina a largura da exibição do conteúdo como, digamos, 1225.
Observe que a largura da visualização de conteúdo agora é 225 maior que a largura da visualização de rolagem pai. Tudo bem: na verdade, você DEVE fazer isso. Observe que
... você NÃO define a largura à direita como 225 negativo ...
você pensaria que tinha que "combinar" as larguras como faria normalmente . Mas se você fizer isso, não funcionará.
Você deve definir os números iniciais e finais como ZERO , nunca negativos (mesmo que a largura seja "maior")
Curiosamente, você pode realmente definir os números iniciais / finais com qualquer valor positivo (tente dizer "50") e isso fornece uma margem de rejeição. (Muitas vezes, parece ótimo: experimente.) Qualquer valor negativo em ambos os lados será "interrompido silenciosamente".
Observe que, irritantemente, geralmente o Xcode (a partir de 7.3.1 de qualquer maneira),
'definirá' com presteza esses valores para números negativos!
porque tenta contabilizá-los automaticamente para você. Nesse caso, ele se romperá silenciosamente. Defina todos os quatro valores como zero na primeira instância. E defina a largura da exibição do conteúdo muito maior que a "1000" no exemplo.
Editado: acabei usando o UITableView em vez do UIScrollView para a maioria dos meus requisitos. Como tableView me parece muito mais flexível e dinâmico.
fonte
Presumo que você esteja tendo problemas com o
contentSize
. Confira esta postagem no blog sobre como lidar com ocontentSize
uso de uma abordagem de AutoLayout "pura". A essência disso é que suas restrições definem implicitamente o tamanho do conteúdo. NUNCA o defina explicitamente ao usar o AutoLayout. Anexei um projeto de exemplo no final da postagem do blog para demonstrar como ele funcionafonte
Há uma parte nas notas técnicas que você pode ter examinado. Você pode definir implicitamente o tamanho do conteúdo de uma exibição de rolagem usando restrições fixadas nas bordas da exibição de rolagem.
Aqui está um exemplo simples. Crie um storyboard com uma vista que tenha uma vista de rolagem. Defina as restrições das visualizações de rolagem para ajustá-las ao tamanho da visualização em que você as inseriu.
Dentro dessa visualização de rolagem, adicione uma única visualização. Defina explicitamente o tamanho dessa exibição usando restrições (e verifique se o tamanho é maior que a exibição de rolagem).
Agora, adicione mais quatro restrições à vista interna, bloqueando as quatro arestas da vista interna em sua vista de rolagem pai. Essas quatro restrições farão com que o tamanho do conteúdo se expanda para acomodar a visualização interna.
Se você tiver várias visualizações que deseja adicionar a uma visualização de rolagem, por exemplo, dispostas horizontalmente, bloqueie o lado esquerdo da primeira subvisão à esquerda da visualização de rolagem, bloqueie as sub-visualizações horizontalmente e a direita lado da última subvisualização ao lado direito da visualização de rolagem. Essas restrições forçariam o tamanho do conteúdo da exibição de rolagem a se expandir para acomodar todas as subvisões e suas restrições.
fonte
Se sua pergunta for "Como coloco um monte de UITextFields em um UIScrollView de rolagem vertical, de forma que eles se afastem do caminho do teclado quando estão focados", a melhor resposta é:
Não.
Use um UITableViewController com células estáticas.
Você obtém esse comportamento de rolagem fora do caminho gratuitamente, E todos os inserções de conteúdo Apenas funcionam se o seu controlador de exibição for exibido dentro de um UINavigationController.
fonte
Você deve organizar seu layout como este
ViewControllerView
contémScrollView
,ScrollView
contémContainerView
,ContainerView
contém 2Labels
Em seguida, siga 3 etapas para fazer a
ScrollView
rolagem da lataScrollView
pino (superior / direito / inferior / esquerdo) paraViewControllerView
ContainerView
pino (superior / direito / inferior / esquerdo) paraScrollView
Horizontally in Container
( não definirVertically in Container
)Label1
pino ( superior / direita / esquerda) paraContainerView
Label1
pino (direita / esquerda / inferior ) paraContainerView
e de cima paraLabel1
Espero que esta ajuda
fonte
A abordagem de autolayout puro funciona perfeitamente, mas é muito difícil configurar se você estiver migrando de um não-autolayout. Já fiz isso algumas vezes e tenho algumas dicas gerais:
fonte
Depois de algum tempo lidando com esse problema, finalmente encontrei uma solução. Estou trabalhando com storyboards de tamanhos de classe universais (600x600). Criei um UIView (contentView) do tamanho do scrollView e criei restrições para Superior, Inferior, Principal e Final no scrollView. Depois, recortei manualmente o tamanho do contentView para 600x600. O storyboard parou de tentar redimensionar tudo e eu pude trabalhar, mas a vista parecia horrível no dispositivo ou simulador real. Fiz 2 tomadas de restrição com esses tamanhos cortados.
Em seguida, em viewDidLoad
Funciona bem.
fonte
Passei dias tentando encontrar uma solução de como usar o AutoLayout para exibir um Scrollview incorporado, para centralizar o scrollview na tela visível, que funciona em todos os dispositivos / dimensões da tela e também na rotação da tela.
Passei dias tentando fazer isso apenas com o Autolayout e cheguei perto, mas nunca perto o suficiente. Então, no final, eu tive que adicionar 3 linhas de código por tela também, no viewDidLoad.
Veja a solução abaixo:
Agora vá para o arquivo .m e adicione essas linhas de código no viewDidLoad (brinque com a quantidade de preenchimento para obter a centragem correta do vert)
{self.constraintVertVtoSV.constant = 150.0; }
agora isso deve ser executado em todos os dispositivos e estar centralizado corretamente e ainda rolar corretamente.
fonte
Se como eu, basta usar conteúdo estático sem restrições dentro da subvisão, como você pode fazer assim:
fonte
Problema semelhante que estou tendo hoje com o iOS 8.4, Xcode 6.4
Existe uma exibição que contém uma exibição de rolagem, contendo um contentView (UIView) contendo sub-visualizações.
Tudo é layout automático em qualquer lugar. As arestas da vista de rolagem são fixadas nas arestas das vistas pai com restrições. As arestas da exibição de conteúdo são fixadas nas arestas da exibição de rolagem com restrições.
Originalmente, a exibição de conteúdo se recusava a dimensionar como a largura total da exibição de rolagem. Eu tive que adicionar uma restrição adicional na exibição de conteúdo para que sua largura correspondesse à exibição de rolagem pai. Ou eu poderia definir uma restrição contentView.centerX == scrollView.centerX. Qualquer um desses, além de fixar as bordas, de repente fez o tamanho da exibição do conteúdo corretamente.
Fixar as bordas da visualização de conteúdo na visualização de rolagem usando restrições visuais do formulário,
Eu uso uma rotina para percorrer a matriz e adicioná-los ao scrollView.
fonte
Eu enfrentei um problema semelhante. Eu defini todas as restrições e sempre me perguntei por que ela ainda redimensiona algumas subvisões. Minha solução foi definir clipsToBounds como YES.
fonte
Em breve você pode usar esta solução de trabalho.
Restrições
ScrollView
: À esquerda, à direita, superior, inferior = visão geralContentView
: À esquerda, à direita, superior, inferior = ScrollView. Altura fixa / relativa ao conteúdo.É possível definir a restrição de largura (contentView) como igual à superview de visualizações de rolagem, mas selecione remover remover no tempo de construção, porque você adicionará essa restrição programaticamente. Isso é apenas para que o IB não reclame com avisos.
E no View Controller
viewDidLayoutSubviews
eu chamo este método:fonte
Sei que esta é uma solução para leigos e não o que a Apple sugere na documentação, mas funcionou duas vezes para mim, com conteúdo diferente e pode ser configurada rapidamente: No controlador de exibição de storyboard, insira o UIView. No UIView, insira uma Visualização de tabela, Dinâmica, 0 protótipo de células, Estilo simples ou Agrupado. Na exibição de tabela, insira uma exibição de rolagem; na exibição de rolagem, insira o conteúdo. É isso, não há configurações no controlador de exibição personalizado.
fonte