4
votes

Ajouter layoutMargins à un élément dans un UIStackView

Je voudrais créer un stackview vertical avec 3 éléments dedans. Je veux un peu plus d'espace uniquement entre le 2ème et le dernier élément. J'ai donc pensé à ajouter au dernier élément:

let v = UIView(frame:CGRect(x:0,y:0,width:100,height:400))
v.backgroundColor = .red
myStackView.addArrangedSubview(v)
//...

Mais les layoutmargins ne sont pas appliqués dans ma stackview. Y a-t-il un moyen facile d'y parvenir (j'aimerais éviter de modifier la hauteur intérieure du dernier élément).

EDIT: J'ai juste essayé d'augmenter la hauteur du 2ème élément (+50) dans son cadre en faisant:

my2ndElementLabel.sizeToFit()
my2ndElementLabel.frame = CGRect(x:my2ndElementLabel.frame.origin.x,y:lmy2ndElementLabel.frame.origin.y,
                                 width:my2ndElementLabel.frame.width, height:my2ndElementLabel.frame.height + 50)

mais cela n'a aucun effet.

EDIT2: J'ai essayé d'ajouter une vue aléatoire à mon UIStackView, mais la vue est simplement ignorée! Vous avez peut-être manqué quelque chose dans la compréhension du fonctionnement d'UIKit? ...:

mylastelement.layoutMargins = UIEdgeInsets(top:30, left:0,bottom:0, right:0)


3 commentaires

Avez-vous essayé d'utiliser des contraintes de mise en page automatique sur l'ancre supérieure?


Que voulez-vous dire exactement ? En fait, je pouvais contraindre chaque vue de haut en bas, mais je voulais utiliser une vue de pile pour m'entraîner à l'utiliser.


Il est étrange qu'il n'y ait aucun moyen d'ajouter une marge à un seul élément d'un Stackview. Il semble que le changement de cadre des vues n'a aucun effet


5 Réponses :


0
votes

Je me suis retrouvé: il semble que UIStackView ne fonctionne pas du tout avec l'ancien système de dimensionnement (avec .frame). Il semble que vous deviez contraindre la hauteur et la largeur, et StackView contraindra la position gauche / haut / droite / bas pour vous lorsque vous ajoutez la sous-vue arrangée.

Ma deuxième vue était une étiquette: je voulais une marge de 40, sous le texte. J'ai donc d'abord calculé la hauteur de l'étiquette dans sa propriété .frame, et j'ai contraint la hauteur à frame.height + 40 (= ma marge)

labelDesc.sizeToFit()
labelDesc.heightAnchor.constraint(equalToConstant:40).isActive = true

Je trouve ma propre solution tout à fait laide bien que. Je suis sûr que UIKit offre un meilleur moyen d'atteindre un objectif aussi simple, sans avoir à faire ce genre de solutions de bricolage. Alors s'il vous plaît, si vous avez l'habitude de travailler avec UIKit, dites-moi s'il existe une meilleure solution.


0 commentaires

1
votes

Dans la même veine générale, vous pouvez contraindre l'ancre supérieure (ou inférieure) de votre vue par rapport au bord correspondant de toute vue dans laquelle elle est intégrée. Ce qui est moche étant un peu une question de goût, je trouve que les contraintes de mise en page automatique sont faciles à utiliser et faciles à raisonner.

Un exemple simple sous Mac OS plutôt que sous iOS:

        let button = ControlFactory.labeledButton("Filter")
        addSubview(button)
        button.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -20).isActive = true
        button.centerXAnchor.constraint(equalTo: centerXAnchor).isActive = true

Ce code particulier vit dans l'initialiseur de vue et positionne un bouton au milieu d'une vue, 20 points vers le haut à partir du bas.


0 commentaires

3
votes

Voici une extension que j'ai faite qui aide à atteindre rapidement de telles marges:

extension UIStackView {

    func addArrangedSubview(_ v:UIView, withMargin m:UIEdgeInsets )
    {
        let containerForMargin = UIView()
        containerForMargin.addSubview(v)
        v.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            v.topAnchor.constraint(equalTo: containerForMargin.topAnchor, constant:m.top ),
            v.bottomAnchor.constraint(equalTo: containerForMargin.bottomAnchor, constant: m.bottom ),
            v.leftAnchor.constraint(equalTo: containerForMargin.leftAnchor, constant: m.left),
            v.rightAnchor.constraint(equalTo: containerForMargin.rightAnchor, constant: m.right)
        ])

        addArrangedSubview(containerForMargin)
    }
}


0 commentaires

3
votes

Vous pouvez définir un espacement personnalisé entre le deuxième et le troisième élément.

myStackView.setCustomSpacing(30.0, after: my2ndElementLabel)


0 commentaires

0
votes

Pensez à ajouter une "marge" en insérant une UIView correctement dimensionnée dans la vue Stack si nécessaire.

Si vous avez besoin d'une marge de 40px entre 2 éléments spécifiques ... ajoutez un UIView avec une contrainte de hauteur de 40px. Attribuez un arrière-plan clearColor pour le rendre invisible.

Vous pouvez ajouter des IBOutlets à cette vue et la masquer comme vous le feriez pour tout autre élément de la vue Pile.


0 commentaires