iOS - 在堆栈视图中以编程方式添加垂直线 [英] iOS - Add vertical line programatically inside a stack view

查看:18
本文介绍了iOS - 在堆栈视图中以编程方式添加垂直线的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to add vertical lines, between labels inside a stack view all programatically.

所需的饰面如下图所示:

The desired finish will be something like this image:

我可以添加标签,所有标签都具有所需的间距;我可以添加水平线,但我不知道如何在中间添加这些分隔线.

I can add the labels, all with the desired spacing; I can add horizontal lines but I can't figure out how to add those separator vertical lines in-between.

我想这样做:

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

有什么提示吗?

谢谢

推荐答案

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

You can't use the same view in two places, so you'll need to create two separate vertical line views. You need to configure each vertical line view like this:

  • 设置其背景颜色.
  • 将其宽度限制为 1(这样您会得到一条线,而不是矩形).
  • 限制它的高度(所以它不会被拉伸到堆栈视图的整个高度).

因此一次将一个标签添加到堆栈视图中,并在将每个标签添加到堆栈视图之前执行以下操作:

So add the labels one at a time to the stack view, and do something like this before adding each label to the stack view:

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
}

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

Note that you do not want the vertical lines to be the same width as the labels, so you must not set the distribution property of the stack view to fillEqually. Instead, if you want all the labels to have equal width, you must create width constraints between the labels yourself. For example, after adding each new label, do this:

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

结果:

完整的操场代码(由 Federico Zanetello 更新到 Swift 4.1):

Full playground code (updated to Swift 4.1 by Federico Zanetello):

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: "
" + 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))

这篇关于iOS - 在堆栈视图中以编程方式添加垂直线的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆