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

Iva*_*ino 10 uiview ios uistackview swift3

我正在尝试以编程方式在堆栈视图内的标签之间添加垂直线.

所需的完成将是这样的图像:

stackview

我可以添加标签,所有标签都有所需的间距; 我可以添加水平线,但我无法弄清楚如何在中间添加这些分隔符垂直线.

我想这样做:

let stackView = UIStackView(arrangedSubviews: [label1, verticalLine, label2, verticalLine, label3])
Run Code Online (Sandbox Code Playgroud)

任何提示?

谢谢

rob*_*off 24

您不能在两个地方使用相同的视图,因此您需要创建两个单独的垂直线视图.您需要像这样配置每个垂直线视图:

  • 设置其背景颜色.
  • 将其宽度约束为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
}
Run Code Online (Sandbox Code Playgroud)

请注意,您希望垂直线与标签的宽度相同,因此您不能distribution堆栈视图的属性设置为fillEqually.相反,如果您希望所有标签具有相等的宽度,则必须自己在标签之间创建宽度约束.例如,在添加每个新标签后,执行以下操作:

if let firstLabel = stackView.arrangedSubviews.first as? UILabel {
    label.widthAnchor.constraint(equalTo: firstLabel.widthAnchor).isActive = true
}
Run Code Online (Sandbox Code Playgroud)

结果:

结果

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

import UIKit
import PlaygroundSupport

extension UIFont {
  var withSmallCaps: UIFont {
    let feature: [UIFontDescriptor.FeatureKey: Any] = [
      UIFontDescriptor.FeatureKey.featureIdentifier: kLowerCaseType,
      UIFontDescriptor.FeatureKey.typeIdentifier: kLowerCaseSmallCapsSelector]
    let attributes: [UIFontDescriptor.AttributeName: Any] = [UIFontDescriptor.AttributeName.featureSettings: [feature]]
    let descriptor = self.fontDescriptor.addingAttributes(attributes)
    return UIFont(descriptor: descriptor, size: pointSize)
  }
}

let rootView = UIView(frame: CGRect(x: 0, y: 0, width: 320, height: 44))
rootView.backgroundColor = .white
PlaygroundPage.current.liveView = rootView

let stackView = UIStackView()
stackView.axis = .horizontal
stackView.alignment = .center
stackView.frame = rootView.bounds
rootView.addSubview(stackView)

typealias Item = (name: String, value: Int)
let items: [Item] = [
  Item(name: "posts", value: 135),
  Item(name: "followers", value: 6347),
  Item(name: "following", value: 328),
]

let valueStyle: [NSAttributedStringKey: Any] = [NSAttributedStringKey.font: UIFont.boldSystemFont(ofSize: 12).withSmallCaps]
let nameStyle: [NSAttributedStringKey: Any] = [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 12).withSmallCaps,
                                NSAttributedStringKey.foregroundColor: UIColor.darkGray]
let valueFormatter = NumberFormatter()
valueFormatter.numberStyle = .decimal

for item in items {
  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.4).isActive = true
  }

  let richText = NSMutableAttributedString()
  let valueString = valueFormatter.string(for: item.value)!
  richText.append(NSAttributedString(string: valueString, attributes: valueStyle))
  richText.append(NSAttributedString(string: "\n" + item.name, attributes: nameStyle))
  let label = UILabel()
  label.attributedText = richText
  label.textAlignment = .center
  label.numberOfLines = 0
  stackView.addArrangedSubview(label)

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

UIGraphicsBeginImageContextWithOptions(rootView.bounds.size, true, 1)
rootView.drawHierarchy(in: rootView.bounds, afterScreenUpdates: true)
let image = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
let png = UIImagePNGRepresentation(image)!
let path = NSTemporaryDirectory() + "/image.png"
Swift.print(path)
try! png.write(to: URL(fileURLWithPath: path))
Run Code Online (Sandbox Code Playgroud)


小智 21

您可以尝试以下方法.

  1. 首先采用UIView并将相同的UIStackView约束应用于此UIView.
  2. 将此UIView的背景颜色设为黑色(线条的颜色)
  3. 现在拿一个UIStackView并将其添加为上面的UIView的孩子.
  4. 添加UIStackView的约束,即将其绑定到父UIView的所有边缘.
  5. 现在将UIStackView的bakckground颜色设置为Clear Color.
  6. 将UIStackView的间距设置为1或2(行的宽度)
  7. 现在将3个标签添加到stackview中.
  8. 确保标签的背景颜色为白色,文本颜色为黑色.

这样你就可以实现所需的场景.请参阅这些图片以供参考.

在此输入图像描述 在此输入图像描述


GOR*_*GOR 6

这是一个简单的扩展,用于在每一行之间添加分隔符(注意!行,而不是所要求的列!对于该情况也很容易修改).与接受的答案基本相同,但是以可重复使用的格式.

通过调用例如使用

yourStackViewObjectInstance.addHorizontalSeparators(color : .black)
Run Code Online (Sandbox Code Playgroud)

延期:

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
    }
}
Run Code Online (Sandbox Code Playgroud)