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:
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
Vous pouvez essayer ce qui suit.
Ainsi, vous obtiendrez la scène requise. Voir ces images pour référence.
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
}
}
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.
@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?