我试图在我的
UIStackViews
边框中给出 5 个单独的 ViewController
。 我给他们每个人一个IBOutlet
,然后在viewDidLoad
中调用他们来使用layer
属性,但没有效果。 是否无法以编程方式给出堆栈视图边框?
代码:
@IBOutlet weak var stackView1: UIStackView!
@IBOutlet weak var stackView2: UIStackView!
@IBOutlet weak var stackView3: UIStackView!
@IBOutlet weak var stackView4: UIStackView!
@IBOutlet weak var stackView5: UIStackView!
override func viewDidLoad() {
super.viewDidLoad()
stackView1.layer.borderWidth = 5
stackView2.layer.borderWidth = 5
stackView3.layer.borderWidth = 5
stackView4.layer.borderWidth = 5
stackView5.layer.borderWidth = 5
}
不幸的是,这是无法做到的。 UIStackView 的不同寻常之处在于它是一个“非渲染”视图,它执行布局(使用自动布局约束)但不显示自身。它有一个像所有 UIView 一样的层,但它被忽略了。
请参阅 Apple 文档“管理堆栈视图的外观”:
UIStackView 是 UIView 的非渲染子类。它不是 提供自己的任何用户界面。相反,它只是管理 其排列视图的位置和大小。结果,一些属性 (如背景颜色)对堆栈视图没有影响。相似地, 您不能覆盖layerClass、drawRect:或drawLayer:inContext:
可以通过将堆栈视图内的视图作为边框来做到这一点。这可能需要大量工作,并且可能在某些情况下不起作用或必须解决,因此可能不值得付出努力。您需要嵌套堆栈视图,以便可以在水平和垂直方向提供边框。在我的Bordered Stack Views 博客文章中,我对此进行了更详细的介绍。但基本上我有常规视图,其背景设置为我选择的颜色,并且根据堆栈视图轴的方向将高度或宽度约束设置为 1。以下是界面构建器中内置 2x2 网格的完整层次结构:
导致这个结果:
这是此示例的我的 github 存储库的链接,以便您可以查看故事板文件。
您可以将 stackView 嵌入到 UIView 中,然后设置该视图的边框(颜色、宽度等),然后将 stackView 约束到该 UIView,如上、左、右、高度。
这是我找到并使用的一段方便的代码:
extension UIView {
func addTopBorderWithColor(color: UIColor, width: CGFloat) {
let border = CALayer()
border.backgroundColor = color.cgColor
border.frame = CGRect(x:0,y: 0, width:self.frame.size.width, height:width)
self.layer.addSublayer(border)
}
func addRightBorderWithColor(color: UIColor, width: CGFloat) {
let border = CALayer()
border.backgroundColor = color.cgColor
border.frame = CGRect(x: self.frame.size.width - width,y: 0, width:width, height:self.frame.size.height)
self.layer.addSublayer(border)
}
func addBottomBorderWithColor(color: UIColor, width: CGFloat) {
let border = CALayer()
border.backgroundColor = color.cgColor
border.frame = CGRect(x:0, y:self.frame.size.height - width, width:self.frame.size.width, height:width)
self.layer.addSublayer(border)
}
func addLeftBorderWithColor(color: UIColor, width: CGFloat) {
let border = CALayer()
border.backgroundColor = color.cgColor
border.frame = CGRect(x:0, y:0, width:width, height:self.frame.size.height)
self.layer.addSublayer(border)
}
func addMiddleBorderWithColor(color: UIColor, width: CGFloat) {
let border = CALayer()
border.backgroundColor = color.cgColor
border.frame = CGRect(x:self.frame.size.width/2, y:0, width:width, height:self.frame.size.height)
self.layer.addSublayer(border)
}
}
只需在任何视图上使用,如下所示:
bottomControls.addMiddleBorderWithColor(color: buttonBorderColor, width: 3.0)
正如其他人所指出的,你不能这样做(详情请参阅 Clafou 的回答)。
但是,您可以做的是将您的堆栈视图嵌入到另一个 UIView 中;对封闭 UIView 的图层进行修改。
我在一个 UIStackView 中有多个 UIStackView。
我只想要堆栈中的一个 UIStackViews 的顶部和底部边框,因此我将有问题的 UIStackView 添加到 UIView 中,并将背景颜色设置为我想要的顶部和底部边框颜色的颜色,并替换了有边框的 UIStackView与 UIView 一起排列的子视图。
import UIKit
import Foundation
let goldBorderedUIView = UIView()
lazy var mainStackView: UIStackView =
{
let mainStack = UIStackView(arrangedSubviews: [goldBorderedUIView, stack2, stack3, stack 4])
mainStack.translatesAutoresizingMaskIntoConstraints = false
mainStack.axis = .vertical
mainStack.spacing = 0.5
mainStack.distribution = .fillEqually
return mainStack
}()
func setupBorderdStack() {
NSLayoutConstraint.activate([
borderedStackView.leadingAnchor.constraint(equalTo: goldBorderedUIView.leadingAnchor),
borderedStackView.topAnchor.constraint(equalTo: goldBorderedUIView.topAnchor, constant: 5),
borderedStackView.trailingAnchor.constraint(equalTo: goldBorderedUIView.trailingAnchor),
borderedStackView.bottomAnchor.constraint(equalTo: goldBorderedUIView.bottomAnchor, constant: -5)
])
}
override func viewDidLoad() {
super.viewDidLoad()
setupBorderdStack()
}
我发现向 UIStackView 添加边框的最简单方法是扩展堆栈视图类,然后添加两个分层视图:底部的视图与堆栈视图的大小相同,顶部的视图使用 mask out边框内侧,稍小一些。
这是 Swift 5 中的扩展:
extension UIStackView {
func addBorder(color: UIColor, backgroundColor: UIColor, thickness: CGFloat) {
let insetView = UIView(frame: bounds)
insetView.backgroundColor = backgroundColor
insetView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
insertSubview(insetView, at: 0)
let borderBounds = CGRect(
x: thickness,
y: thickness,
width: frame.size.width - thickness * 2,
height: frame.size.height - thickness * 2)
let borderView = UIView(frame: borderBounds)
borderView.backgroundColor = color
borderView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
insertSubview(borderView, at: 0)
}
}
然后通过这样的调用添加边框:
myStackView.addBorder(color: .lightGray, backgroundColor: .white, thickness: 2)
是的,向 UIStackView 应用边框很简单。就我而言,我有一个嵌套的 UIStackViews,我可以使用以下代码设置 borderColor、borderWidth 和cornerRadius:
myStackView.borderColor = UIColor(red: 25.0/255.0, green: 24.0/255.0, blue: 35.0/255.0, alpha: 0.15)
myStackView.borderWidth = 1.0
myStackView.cornerRadius = 4.0
这就是堆栈视图内容周围空间
24px
的创建方式。
let myStackView = [oneStack, twoStack, threeStack].stack(axis: .vertical, distribution: .fill, alignment: .fill, spacing: 16)
myStackView.layoutMargins = UIEdgeInsets(top: 24, left: 24, bottom: 24, right: 24)
myStackView.isLayoutMarginsRelativeArrangement = true
如果需要对上例中的
oneStack
等应用边框,只需要扩展逻辑即可设置borderColor
、borderWidth
和cornerRadius
。