web-dev-qa-db-fra.com

iOS - Ajouter une ligne verticale par programme dans une vue de pile

J'essaie d'ajouter des lignes verticales, entre les étiquettes à l'intérieur d'une pile, toutes les vues par programme.

La finition souhaitée ressemblera à cette image:

 stackview

Je peux ajouter les étiquettes, toutes avec l'espacement souhaité; Je peux ajouter des lignes horizontales, mais je ne vois pas comment ajouter ces lignes de séparation verticales entre les deux.

Je voudrais faire quelque chose comme ça:

let stackView = UIStackView(arrangedSubviews: [label1, verticalLine, label2, verticalLine, label3])

Un indice?

Merci

9
Ivan Cantarino

Vous pouvez essayer ce qui suit. 

  1. Tout d’abord, prenez un UIView et appliquez les mêmes contraintes d’UIStackView à ce UIView.
  2. Faire la couleur de fond de cette UIView au noir (La couleur des lignes)
  3. Maintenant, prenez un UIStackView et ajoutez-le comme un enfant de UIView ci-dessus.
  4. Ajoutez des contraintes de UIStackView, c'est-à-dire que vous le liez à tous les bords de UIView parent.
  5. Créez maintenant la couleur de fond de UIStackView en Clear Color.
  6. Définissez l'espacement de UIStackView sur 1 ou 2 (la largeur des lignes)
  7. Maintenant, ajoutez les 3 étiquettes dans stackview.
  8. Assurez-vous que la couleur d'arrière-plan des étiquettes est Blanc et Couleur du texte et Noir.

Ainsi, vous obtiendrez la scène requise. Voir ces images pour référence.

 enter image description here  enter image description here

13
Himanshu Garg

Voici une simple extension permettant d’ajouter des séparateurs entre chaque ligne (NOTE! Les lignes, pas les colonnes comme il est demandé! Simple à modifier pour ce cas également). Fondamentalement identique à la réponse acceptée, mais dans un format réutilisable.

Utiliser en appelant par exemple 

yourStackViewObjectInstance.addHorizontalSeparators(color : .black)

Extension:

extension UIStackView {
    func addHorizontalSeparators(color : UIColor) {
        var i = self.arrangedSubviews.count
        while i >= 0 {
            let separator = createSeparator(color: color)
            insertArrangedSubview(separator, at: i)
            separator.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 1).isActive = true
            i -= 1
        }
    }

    private func createSeparator(color : UIColor) -> UIView {
        let separator = UIView()
        separator.heightAnchor.constraint(equalToConstant: 1).isActive = true
        separator.backgroundColor = color
        return separator
    }
}
5
GOR

Si le caractère de ligne verticale, "|", correspond au style souhaité, vous pouvez ajouter des étiquettes dans la vue de pile où vous souhaitez des lignes de séparation. Alors utilisez:

myStackView.distribution = .equalSpacing

Vous pouvez également modifier la distribution de la vue de pile dans Interface Builder.

0
iOS_Mouse

@GOR answer extension uniquement pour la ligne verticale et uniquement dans les centres

Paramètres Stackview: définissez les contraintes de largeur de chaque sous-vue et empilement de la vue parent doit être remplie

Voici une extension simple pour ajouter des séparateurs verticaux entre chaque ligne.

func addVerticalSeparators(color : UIColor) {
    var i = self.arrangedSubviews.count
    while i > 1 {
        let separator = verticalCreateSeparator(color: color)
        insertArrangedSubview(separator, at: i-1)   // (i-1) for centers only
        separator.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1).isActive = true
        i -= 1
    }
}

private func verticalCreateSeparator(color : UIColor) -> UIView {
    let separator = UIView()
    separator.widthAnchor.constraint(equalToConstant: 1).isActive = true
    separator.backgroundColor = color
    return separator
} 

Voici une sous-classe UIStackView plus flexible qui prend en charge l’ajout arbitraire de sous-vues organisées et convient à ceux qui ont besoin d’un contexte clair sur leur UIStackView et de sous-vues à placer au-dessus d’une UIVisualEffectView, comme sur l’image ci-dessous.

import UIKit

@IBDesignable class SeparatorStackView: UIStackView {

    @IBInspectable var separatorColor: UIColor? = .black {
        didSet {
            invalidateSeparators()
        }
    }
    @IBInspectable var separatorWidth: CGFloat = 0.5 {
        didSet {
            invalidateSeparators()
        }
    }
    @IBInspectable private var separatorTopPadding: CGFloat = 0 {
        didSet {
            separatorInsets.top = separatorTopPadding
        }
    }
    @IBInspectable private var separatorBottomPadding: CGFloat = 0 {
        didSet {
            separatorInsets.bottom = separatorBottomPadding
        }
    }
    @IBInspectable private var separatorLeftPadding: CGFloat = 0 {
        didSet {
            separatorInsets.left = separatorLeftPadding
        }
    }
    @IBInspectable private var separatorRightPadding: CGFloat = 0 {
        didSet {
            separatorInsets.right = separatorRightPadding
        }
    }

    var separatorInsets: UIEdgeInsets = .zero {
        didSet {
            invalidateSeparators()
        }
    }

    private var separators: [UIView] = []

    override func layoutSubviews() {
        super.layoutSubviews()

        invalidateSeparators()
    }

    override func awakeFromNib() {
        super.awakeFromNib()

        invalidateSeparators()
    }

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()

        invalidateSeparators()
    }


    private func invalidateSeparators() {
        guard arrangedSubviews.count > 1 else {
            separators.forEach({$0.removeFromSuperview()})
            separators.removeAll()
            return
        }

        if separators.count > arrangedSubviews.count {
            separators.removeLast(separators.count - arrangedSubviews.count)
        } else if separators.count < arrangedSubviews.count {
            separators += Array<UIView>(repeating: UIView(), count: arrangedSubviews.count - separators.count)
        }

        separators.forEach({$0.backgroundColor = self.separatorColor; self.addSubview($0)})

        for (index, subview) in arrangedSubviews.enumerated() where arrangedSubviews.count >= index + 2 {
            let nextSubview = arrangedSubviews[index + 1]
            let separator = separators[index]

            let Origin: CGPoint
            let size: CGSize

            if axis == .horizontal {
                let originX = (nextSubview.frame.maxX - subview.frame.minX)/2 + separatorInsets.left - separatorInsets.right
                Origin = CGPoint(x: originX, y: separatorInsets.top)
                let height = frame.height - separatorInsets.bottom - separatorInsets.top
                size = CGSize(width: separatorWidth, height: height)
        } else {
                let originY = (nextSubview.frame.maxY - subview.frame.minY)/2 + separatorInsets.top - separatorInsets.bottom
                Origin = CGPoint(x: separatorInsets.left, y: originY)
                let width = frame.width - separatorInsets.left - separatorInsets.right
                size = CGSize(width: width, height: separatorWidth)
            }

            separator.frame = CGRect(Origin: Origin, size: size)
        }
    }
}

Le résultat?

 SeparatorStackView on top of a UIVisualEffectView

0
Mark Bourke