Como adicionar preenchimento à esquerda para visualização adicionado dentro de um UIStackView

125

Esta é a minha configuração: Eu tenho um UIScrollViewcom borda superior, superior e de teste definida como 0. Dentro disso, adiciono um UIStackViewcom estas restrições:

stackView.centerYAnchor.constraintEqualToAnchor(selectedContactsScrollView.centerYAnchor).active = true  
stackView.leadingAnchor.constraintEqualToAnchor(selectedContactsScrollView.leadingAnchor).active = true

Dentro da visualização da pilha, adiciono algumas visualizações.
Meu problema é que, devido às restrições, a primeira exibição adicionada à exibição em pilha também terá borda inicial = 0.

Quais são as maneiras pelas quais eu poderia adicionar algum preenchimento à primeira exibição? Sem ajustar as restrições da exibição de rolagem.

Adrian
fonte
2
você gostaria de mudar a resposta aceita? A resposta de Tolga parece muito melhor.
Mel

Respostas:

26

A solução que você forneceu não adiciona um preenchimento às suas visualizações no UIStackView (como você queria na pergunta), mas adiciona um líder para o UIStackView.

Uma solução poderia ser adicionar outro UIStackView dentro do seu UIStackView original e dar a liderança a este novo UIStackVIew. Em seguida, adicione suas visualizações a este novo UIStackView.

Dica, você pode fazer isso completamente usando o Interface Builder. Em outras palavras, não há necessidade de escrever código para ele.

William Kinaan
fonte
373

Quando a isLayoutMarginsRelativeArrangementpropriedade for verdadeira, a exibição da pilha exibirá suas exibições organizadas em relação às margens do layout.

stackView.layoutMargins = UIEdgeInsets(top: 0, left: 20, bottom: 0, right: 20)
stackView.isLayoutMarginsRelativeArrangement = true

Mas isso afeta todas as visualizações organizadas dentro da exibição da pilha. Se você desejar esse preenchimento para apenas uma exibição organizada, precisará usar aninhadosUIStackView

Tolga Okur
fonte
2
isLayoutMarginsRelativeArrangementé um getter, setter é layoutMarginsRelativeArrangement. Não consigo editar a resposta
maross 31/03
5
@ maross não há diferença entre a função getter e setter no Swift. Mas você está certo, as pessoas que desenvolvem com o Objective-C devem usar layoutMarginsRelativeArrangement. Documentação oficial: developer.apple.com/reference/uikit/uistackview/...
Tolga Okur
3
Para Objective-C:stackView.layoutMargins = UIEdgeInsetsMake(0, 20, 0, 20); [stackView setLayoutMarginsRelativeArrangement:YES];
Snouto 27/11
4
Fevereiro de 2019, à meia-noite, sentado no escritório - Respostas como essas me dão forças para seguir em frente. Obrigado @tolpp
nefarianblack
155

Eu descobri que as restrições não funcionam dentro de um Stack View, ou parecem um pouco estranhas.

(Por exemplo, se eu adicionar restrição à esquerda / à direita à selecionada no stackview da imagem, isso também adicionará à vista à coleção, mas não à direita; e será um conflito, com certeza).

stackview dentro stackview

Para definir margens de layout para todas as visualizações dentro da pilha, selecione:

Stack View > Size Inspector > Layout Margins > Fixed

Nota: a "Fixed"opção foi chamada anteriormente "Explicit", como visto nas capturas de tela.

Em seguida, adicione seu preenchimento:

storyboard

Zaporozhchenko Oleksandr
fonte
23
uma das coisas que a Apple esconde. Eu odeio como o Xcode é o oposto de bom, amigável e fácil. Graças
Duck
O Xcode continua travando quando eu altero essas margens explícitas de layout. Arquivou um bug, mas eles responderam que era uma duplicata.
precisa saber é o seguinte
Isso é o que não consegui encontrar na interface do usuário. Altere as margens do layout para explícito para ver os campos das margens do Stack View.
pkamb
13
O FYI XCode 9 agora chama isso de "Fixo" em vez de "Explícito".
Mel
Também no Xcode 9, desmarque a opção "Usar guias de layout de área segura" no Inspetor de arquivos, que, por escrito, ainda causa muitos problemas no IB, e siga as guias de layout normais para suas restrições.
PJ_Finnegan
16

O que funcionou para mim é adicionar à exibição em pilha outro UIView que seja apenas um espaçador (funciona pelo menos com stackView.distribution = .Fill):

let spacerView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
stackView.addArrangedSubview(spacerView)
stackView.addArrangedSubview(viewThatNeedsSpaceBeforeIt)
stackView.addArrangedSubview(NextView)...
dorsz
fonte
6

swift 3: você só precisa definir o deslocamento por:

firstView.leadingAnchor.constraint(equalTo: parentView.leadingAnchor, constant: 200).isActive = true

Certifique-se de que essa restrição seja definida após você parentView.addArrangdSubView(firstView)

William Hu
fonte
4

Se você precisar apenas de preenchimento à esquerda, defina o Alinhamento da visualização da pilha como "Trailing" e estará livre para especificar restrições de Leading exclusivas em cada uma de suas sub-visões contidas.

Como bônus, você também pode definir o alinhamento da visualização da pilha como "Centro" e, em seguida, usar as restrições à esquerda e / ou à direita para dar a cada item seu próprio preenchimento nos dois lados.

Jonathan Parham
fonte
1

Esta pergunta já tem boas respostas. Porém, uma sugestão, use a spacingpropriedade para definir o espaçamento entre as visualizações. Para a primeira e a última visualizações, pode haver duas opções: definir inserções como o @tolpp sugeriu ou adicionar restrições anexadas ao pai (stackview) com constante para adicionar preenchimento.

Loop infinito
fonte
0

O que fizemos foi adicionar componentes transparentes (por exemplo, UIButton / UIView) como o primeiro e o último filho do UIStackView. Em seguida, defina restringir a largura desses filhos invisíveis para ajustar o preenchimento.

Crashalot
fonte
0

A solução seria ter uma exibição regular na exibição da pilha para armazenar as visualizações às quais você deseja adicionar restrições e, em seguida, você pode adicionar restrições para os itens que são relativos às exibições na exibição da pilha. Dessa forma, suas visualizações originais podem ter restrições iniciais e finais na visualização de pilha.

Isso pode ser feito no construtor de interface e programaticamente.

Aiden Dixon
fonte
-3

Parece que a solução foi bem simples. Ao invés de:

stackView.leadingAnchor.constraintEqualToAnchor(selectedContactsScrollView.leadingAnchor).active = true

Eu acabei de escrever:

stackView.leadingAnchor.constraintEqualToAnchor(selectedContactsScrollView.leadingAnchor, constant: 15).active = true
Adrian
fonte
1
na verdade, o código adiciona um líder para o uistackview dentro do urscrollview, ele não adiciona um padding para seus pontos de vista dentro do seu uistackview, (como a questão Unidos)
William Kinaan
Sim, mas não sei se você pode adicionar preenchimento, portanto isso funcionará para mim.
Adrian
como primeiro pensamento, você pode outro uistackview dentro do uistackview original e fornecer o preenchimento a ele. em seguida, adicionar os seus pontos de vista a este novo uistackview (você pode fazer isso completamente de construtor de interface, não há necessidade de escrever código para ele)
William Kinaan
Sim, isso vai funcionar. Você pode adicionar como resposta e eu aceito.
Adrian