iOS-在堆栈视图中以编程方式添加垂直线

iOS-在堆栈视图中以编程方式添加垂直线,ios,uiview,swift3,uistackview,Ios,Uiview,Swift3,Uistackview,我试图通过编程在堆栈视图中的标签之间添加垂直线 所需的表面处理类似于下图: 我可以添加标签,所有标签都具有所需的间距;我可以添加水平线,但我不知道如何在两者之间添加分隔符垂直线 我想这样做: let stackView = UIStackView(arrangedSubviews: [label1, verticalLine, label2, verticalLine, label3]) 有什么提示吗 谢谢您可以尝试以下方法 首先,获取UIView并将UIStackView的相同约束应用于此

我试图通过编程在堆栈视图中的标签之间添加垂直线

所需的表面处理类似于下图:

我可以添加标签,所有标签都具有所需的间距;我可以添加水平线,但我不知道如何在两者之间添加分隔符垂直线

我想这样做:

let stackView = UIStackView(arrangedSubviews: [label1, verticalLine, label2, verticalLine, label3])
有什么提示吗


谢谢

您可以尝试以下方法

  • 首先,获取UIView并将UIStackView的相同约束应用于此UIView
  • 将此UIView的背景色设置为黑色(线条的颜色)
  • 现在获取UIStackView并将其添加为上面UIView的子级
  • 添加UIStackView的约束,即将其绑定到父UIView的所有边
  • 现在将视图的bakckground颜色设置为Clear color
  • 将视图的间距设置为1或2(线的宽度)
  • 现在将3个标签添加到stackview中
  • 确保标签的背景色为白色,文本色为黑色
  • 因此,您将获得所需的场景。请看这些图片以供参考


    不能在两个位置使用同一视图,因此需要创建两个单独的垂直线视图。您需要如下配置每个垂直线视图:

    let stackView = UIStackView(arrangedSubviews: [label1, verticalLine, label2, verticalLine, label3])
    
    • 设置其背景色
    • 将其宽度限制为1(这样可以得到一条线,而不是一个矩形)
    • 约束其高度(使其不会拉伸到堆栈视图的完整高度)
    因此,将标签一次添加一个到堆栈视图,并在将每个标签添加到堆栈视图之前执行以下操作:

    if stackView.arrangedSubviews.count > 0 {
        let separator = UIView()
        separator.widthAnchor.constraint(equalToConstant: 1).isActive = true
        separator.backgroundColor = .black
        stackView.addArrangedSubview(separator)
        separator.heightAnchor.constraint(equalTo: stackView.heightAnchor, multiplier: 0.6).isActive = true
    }
    
    请注意,您不希望垂直线与标签的宽度相同,因此必须将堆栈视图的
    分布
    属性设置为
    均匀填充
    。相反,如果希望所有标签的宽度相等,则必须自己在标签之间创建宽度约束。例如,添加每个新标签后,请执行以下操作:

    if let firstLabel = stackView.arrangedSubviews.first as? UILabel {
        label.widthAnchor.constraint(equalTo: firstLabel.widthAnchor).isActive = true
    }
    
    结果:

    完整游乐场代码(由Federico Zanetello更新为Swift 4.1):


    这里有一个更灵活的
    UIStackView
    子类,它支持任意添加排列的子视图,适用于那些需要在其
    UIStackView
    上有清晰背景的人,以及需要将子视图置于
    UIVisualEffectView
    之上的人,如下图所示

    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)
            }
        }
    }
    
    导入UIKit
    @IBDesignable类分隔符StackView:UIStackView{
    @i可检测的var分离器颜色:UIColor?=黑色{
    迪塞特{
    无效分隔符()
    }
    }
    @IBInspectable var分离器宽度:CGFloat=0.5{
    迪塞特{
    无效分隔符()
    }
    }
    @IBInspectable专用变量分隔符OppAdding:CGFloat=0{
    迪塞特{
    separatorInsets.top=separatorTopPadding
    }
    }
    @IBInspectable私有变量分隔符BottomAdding:CGFloat=0{
    迪塞特{
    separatorInsets.bottom=separatorbottom
    }
    }
    @IBInspectable private var separatorLeftPadding:CGFloat=0{
    迪塞特{
    separatorInsets.left=separatorLeftPadding
    }
    }
    @IBInspectable private var separatorRightPadding:CGFloat=0{
    迪塞特{
    separatorInsets.right=separatorright填充
    }
    }
    变量分隔项集:UIEdgeInsets=.0{
    迪塞特{
    无效分隔符()
    }
    }
    专用变量分隔符:[UIView]=[]
    覆盖func布局子视图(){
    super.layoutSubviews()
    无效分隔符()
    }
    重写func awakeFromNib(){
    super.awakeFromNib()
    无效分隔符()
    }
    重写func prepareForInterfaceBuilder(){
    super.prepareforPrinterFaceBuilder()
    无效分隔符()
    }
    私有函数无效分隔符(){
    guard arrangedSubviews.count>1其他{
    分隔符.forEach({$0.removeFromSuperview()})
    分隔符。removeAll()
    返回
    }
    如果separators.count>arrangedSubviews.count{
    separators.removeLast(separators.count-arrangedSubviews.count)
    }如果separators.count=索引+2{
    让nextSubview=排列的子视图[索引+1]
    设分隔符=分隔符[索引]
    让原点:CGPoint
    让大小:CGSize
    如果轴==。水平{
    设originX=(nextSubview.frame.maxX-subview.frame.minX)/2+separatorInsets.left-separatorInsets.right
    原点=CGPoint(x:originX,y:separatorInsets.top)
    let height=frame.height-separatorInsets.bottom-separatorInsets.top
    大小=CGSize(宽度:分隔符宽度,高度:高度)
    }否则{
    让originY=(nextSubview.frame.maxY-subview.frame.minY)/2+separatorInsets.top-separatorInsets.bottom
    原点=CGPoint(x:separatorInsets.left,y:originY)
    let width=frame.width-separatorInsets.left-separatorInsets.right
    大小=CGSize(宽度:宽度,高度:分隔符宽度)
    }
    separator.frame=CGRect(原点:原点,大小:大小)
    }
    }
    }
    
    结果如何


    如果垂直线字符“|”适用于所需的外观,则可以将标签添加到堆栈视图中需要分隔线的位置。然后使用:

    myStackView.distribution = .equalSpacing
    
    您还可以在Interface Builder中更改堆栈视图分布。

    下面是一个简单的exte
    yourStackViewObjectInstance.addHorizontalSeparators(color : .black)
    
    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
        }
    }
    
    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
    } 
    
    
    extension UIStackView {
        func addVerticalSeparators(color : UIColor, multiplier: CGFloat = 0.5) {
            var i = self.arrangedSubviews.count - 1
            while i > 0 {
                let separator = createSeparator(color: color)
                insertArrangedSubview(separator, at: i)
                separator.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: multiplier).isActive = true
                i -= 1
            }
        }
    
        private func createSeparator(color: UIColor) -> UIView {
            let separator = UIView()
            separator.widthAnchor.constraint(equalToConstant: 1).isActive = true
            separator.backgroundColor = color
            return separator
        }
    }
    
    extension UIStackView {
        func addHorizontalSeparators(color : UIColor) {
            let separatorsToAdd = self.arrangedSubviews.count - 1
            var insertAt = 1
            for _ in 1...separatorsToAdd {
                let separator = createSeparator(color: color)
                insertArrangedSubview(separator, at: insertAt)
                insertAt += 2
                separator.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1).isActive = true
            }
        }
    
        private func createSeparator(color : UIColor) -> UIView {
            let separator = UIView()
            separator.widthAnchor.constraint(equalToConstant: 1).isActive = true
            separator.backgroundColor = color
            return separator
        }
    }
    
    extension UIStackView {
    
    func addSeparators(at positions: [Int], color: UIColor) {
        for position in positions {
            let separator = UIView()
            separator.backgroundColor = color
            
            insertArrangedSubview(separator, at: position)
            switch self.axis {
            case .horizontal:
                separator.widthAnchor.constraint(equalToConstant: 1).isActive = true
                separator.heightAnchor.constraint(equalTo: self.heightAnchor, multiplier: 1).isActive = true
            case .vertical:
                separator.heightAnchor.constraint(equalToConstant: 1).isActive = true
                separator.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 1).isActive = true
            @unknown default:
                fatalError("Unknown UIStackView axis value.")
            }
        }
    }
    
    stackView.addSeparators(at: [2], color: .black)