35

我试图UIStackViews在我的ViewController边界上分开 5 个。我给了他们每个人一个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   
}
4

9 回答 9

43

不幸的是,这是无法做到的。UIStackView 的不寻常之处在于它是一个“非渲染”视图,它执行布局(使用自动布局约束)但不显示自身。它有一个像所有 UIView 一样的层,但它被忽略了。

请参阅“管理堆栈视图的外观”下的 Apple 文档:

UIStackView 是 UIView 的非渲染子类。它不提供任何自己的用户界面。相反,它只管理其排列视图的位置和大小。因此,某些属性(如 backgroundColor)对堆栈视图没有影响。同样,您不能覆盖 layerClass、drawRect: 或 drawLayer:inContext:

于 2015-12-10T21:32:17.593 回答
16

可以通过将堆栈视图内的视图作为边框来做到这一点。这可能需要大量工作,并且可能存在某些无法工作或必须解决的情况,因此可能不值得付出努力。您需要嵌套堆栈视图,以便可以在水平和垂直方向上提供边框。在我的Bordered Stack Views 博客文章中,我对此进行了更详细的介绍。但基本上我有常规视图将背景设置为我选择的颜色,并且我根据堆栈视图轴的方向给出高度或宽度约束 1。这是在界面生成器中内置的 2x2 网格的完整层次结构:

视图层次结构

导致这个结果:

在此处输入图像描述

这是此示例的我的 github 存储库的链接,因此您可以查看情节提要文件。

于 2016-03-17T23:23:08.017 回答
13

您可以在 UIView 中嵌入 stackView,然后设置该视图的边框(颜色、宽度等),然后将 stackView 约束到该 UIView,例如顶部、左侧、右侧、高度。

于 2016-06-30T14:27:43.210 回答
5

这是我找到并使用的一段方便的代码:

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)

资料来源:如何在 UIButton 上仅添加 TOP 边框?

于 2018-03-09T17:25:34.050 回答
2

正如其他人指出的那样,您不能这样做(有关详细信息,请参阅 Clafou 的答案)。

但是,您可以将堆栈视图嵌入到另一个 UIView 中;对封闭的 UIView 的层进行修改。

于 2018-08-14T19:32:55.183 回答
1

我在 UIStackView 中有多个 UIStackViews。

我只想要堆栈中的一个 UIStackViews 的顶部和底部边框,所以我将有问题的 UIStackView 添加到 UIView 中,背景颜色设置为我想要的顶部和底部边框颜色的颜色,并替换了带边框的 UIStackView用 UIView 排列的Subviews。

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()
    }
于 2020-06-15T05:40:08.143 回答
1

我认为最简单的方法是不再使用高度/宽度等于 1 的标签或视图来表示边框,我的意思是它比使用堆栈视图本身的 SPACING 属性更容易。只需填充您的堆栈及其物质,然后为外部垂直堆栈设置一个间距,也为内部水平堆栈设置一个间距,您将获得完美的效果。最后,为了给边框赋予特定的颜色,我使用外部 stckview 的背景视图来维护它,它与堆栈一样具有与背景颜色相同的约束,就像您希望边框一样,想法是当您设置间距时,间距采用后面的视图颜色堆栈,就是这样:D,请检查附件中的结果,如果有任何不清楚的地方请告诉我 在此处输入图像描述

于 2018-10-31T12:33:12.983 回答
0

我发现向 UIStackView 添加边框的最简单方法是扩展堆栈视图类,然后添加两个分层视图:底部的一个与堆栈视图的大小相同,顶部的一个用于屏蔽边界内,稍微小一点。

这是 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)
于 2020-04-28T20:00:07.407 回答
0

像这样使用

loseWeight.layer.borderColor = UIColor.orange.cgColor
loseWeight.layer.borderWidth = 1

在此处输入图像描述

于 2022-02-03T07:34:35.613 回答