Comment ajouter un remplissage principal à la vue ajoutée à l'intérieur d'un UIStackView

127

Voici ma configuration: j'ai un UIScrollViewbord avant, supérieur et d'essai défini sur 0. À l'intérieur, j'ajoute un UIStackViewavec ces contraintes:

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

Dans la vue de la pile, j'ajoute quelques vues.
Mon problème est qu'en raison des contraintes, la première vue ajoutée à la vue de la pile aura également un bord avant = 0.

Comment puis-je ajouter du remplissage à la première vue? Sans ajuster les contraintes de la vue de défilement.

Adrian
la source
2
voudriez-vous changer la réponse acceptée? La réponse de Tolga semble bien meilleure.
Honey

Réponses:

27

La solution que vous avez fournie n'ajoute pas de remplissage pour vos vues à l'intérieur de votre UIStackView (comme vous le vouliez dans la question), mais elle ajoute une tête pour UIStackView.

Une solution pourrait être d'ajouter un autre UIStackView à l'intérieur de votre UIStackView d'origine et de donner le début à ce nouveau UIStackVIew. Ensuite, ajoutez vos vues à ce nouveau UIStackView.

Astuce, vous pouvez le faire complètement en utilisant Interface Builder. En d'autres termes, pas besoin d'écrire du code pour cela.

William Kinaan
la source
375

Lorsque la isLayoutMarginsRelativeArrangementpropriété est true, la vue de la pile met en page ses vues organisées par rapport à ses marges de disposition.

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

Mais cela affecte toutes les vues organisées à l'intérieur de la vue de pile. Si vous souhaitez ce remplissage pour une seule vue organisée, vous devez utiliserUIStackView

Tolga Okur
la source
2
isLayoutMarginsRelativeArrangementest un getter, un setter est layoutMarginsRelativeArrangement. Je ne peux pas modifier la réponse
maross
5
@maross il n'y a aucune différence entre la fonction getter et setter dans Swift. Mais vous avez raison, les personnes qui développent avec Objective-C devraient utiliser à la layoutMarginsRelativeArrangementplace. Documentation officielle: developer.apple.com/reference/uikit/uistackview/…
Tolga Okur
3
Pour Objective-C:stackView.layoutMargins = UIEdgeInsetsMake(0, 20, 0, 20); [stackView setLayoutMarginsRelativeArrangement:YES];
Snouto
4
Fév 2019, à minuit assis au bureau - Des réponses comme celles-ci me donnent la force d'aller de l'avant. Merci @tolpp
nefarianblack
156

J'ai trouvé que les contraintes ne fonctionnent pas dans une vue de pile, ou elles semblent quelque peu étranges.

(Par exemple, si j'ajoute une contrainte de début / de fin à la sélection sur la vue de la pile de l'image, cela ajoute également le menant à la vue de collection, mais n'ajoute pas de fin; et il y a un conflit à coup sûr).

stackview dans stackview

Pour définir les marges de mise en page pour toutes les vues à l'intérieur de la vue de pile, sélectionnez:

Stack View > Size Inspector > Layout Margins > Fixed

Remarque: l' "Fixed"option était anciennement appelée "Explicit", comme le montrent les captures d'écran.

Ajoutez ensuite votre rembourrage:

storyboard

Zaporozhchenko Oleksandr
la source
23
l'une des choses qu'Apple cache. Je déteste la façon dont Xcode est le contraire de bon, convivial et facile. Merci
Canard
Xcode continue de planter lorsque je change ces marges de mise en page explicites. A déposé un bogue mais ils ont répondu que c'était un double.
mvandillen
C'est ce que je n'ai pas trouvé dans l'interface utilisateur. Remplacez les marges de mise en page par explicites pour afficher les champs des marges de la vue pile.
pkamb
13
FYI XCode 9 appelle maintenant cela "Fixed" au lieu de "Explicit".
Mel
Toujours dans Xcode 9, décochez "Utiliser les guides de mise en page de la zone de sécurité" dans l'inspecteur de fichiers, ce qui, au moment de l'écriture, pose encore beaucoup de problèmes dans IB, et respectez les guides de mise en page normaux pour vos contraintes.
PJ_Finnegan
16

Ce qui a fonctionné pour moi, c'est d'ajouter à la vue de la pile un autre UIView qui n'est qu'un espaceur (fonctionne au moins avec 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
la source
6

swift 3: il vous suffit de définir le décalage de:

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

Assurez-vous que cette contrainte est définie après parentView.addArrangdSubView(firstView)

William Hu
la source
4

Si vous n'avez besoin que d'un remplissage de début, vous pouvez définir l'alignement de la vue de pile sur "Fin" et vous serez alors libre de spécifier des contraintes de début uniques sur chacune de ses sous-vues contenues.

En prime, vous pouvez également définir l'alignement de la vue de la pile sur "Centre", puis vous pouvez utiliser les contraintes de début et / ou de fin pour donner à chaque élément son propre remplissage des deux côtés.

Jonathan Parham
la source
1

Cette question a déjà de bonnes réponses, une suggestion cependant, utilisez la spacingpropriété pour définir l'espacement entre les vues. Pour la première et la dernière vue, il peut y avoir deux options, soit définir des insertions comme @tolpp suggéré, soit ajouter une contrainte attachée au parent (stackview) avec une constante pour ajouter un remplissage.

boucle infinie
la source
1

La solution serait d'avoir une vue régulière dans la vue de la pile pour contenir les vues auxquelles vous souhaitez ajouter des contraintes, puis vous pouvez ajouter des contraintes pour vos éléments qui sont relatives aux vues de la vue de la pile. De cette façon, vos vues d'origine peuvent avoir des contraintes de début et de fin dans la vue de pile.

Cela peut être fait dans le générateur d'interface et par programme.

Aiden Dixon
la source
0

Ce que nous avons fait a été d'ajouter des composants transparents (par exemple, UIButton / UIView) en tant que premier et dernier enfants de UIStackView. Ensuite, définissez contraindre la largeur de ces enfants invisibles pour ajuster le remplissage.

Crashalot
la source
-3

Il semble que la solution était assez simple. Au lieu de:

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

Je viens d'écrire:

stackView.leadingAnchor.constraintEqualToAnchor(selectedContactsScrollView.leadingAnchor, constant: 15).active = true
Adrian
la source
1
en fait, votre code ajoute un début pour uistackview à l'intérieur de urscrollview, il n'ajoute pas de remplissage pour vos vues à l'intérieur de votre uistackview, (comme l'indique la question)
William Kinaan
ouais, mais je ne sais pas si vous pouvez ajouter un rembourrage, donc cela fonctionnera pour moi.
Adrian le
en premier lieu, vous pouvez un autre uistackview à l'intérieur de votre uistackview d'origine et lui donner le rembourrage. puis ajoutez vos vues à ce nouvel uistackview (vous pouvez le faire complètement par le constructeur d'interface, pas besoin d'écrire du code pour cela)
William Kinaan
Oui, cela fonctionnera. Vous pouvez l'ajouter comme réponse et je l'accepterai.
Adrian