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])
有什么提示吗
谢谢您可以尝试以下方法
不能在两个位置使用同一视图,因此需要创建两个单独的垂直线视图。您需要如下配置每个垂直线视图:
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)