IBDesignable 在添加到 UIStackView 时不起作用

IBDesignable not working when added to UIStackView

我有这个相当简单的 IBDesignable RoundedLabel。它在 Interface Builder 中和在模拟器中 运行 时呈现良好。如果我将视图添加到 UIStackView,即使它在 IB 中呈现良好,角半径仅应用于左上角。

import UIKit

@IBDesignable class RoundedLabel: UILabel {
    @IBInspectable var cornerRadius : CGFloat = 46 {
        didSet {
            self.drawTheLabel()
        }
    }

    @IBInspectable var roundRightCorners : Bool = false {
        didSet {
            self.drawTheLabel()
        }
    }

    @IBInspectable var roundLeftCorners : Bool = false {
        didSet {
            self.drawTheLabel()
        }
    }
    @IBInspectable var borderRadius : CGFloat = 3 {
        didSet {
            self.layer.borderWidth = borderRadius
        }
    }
    @IBInspectable var borderColor : UIColor = .black {
        didSet {
            self.layer.borderColor = borderColor.cgColor
        }
    }

    private func drawTheLabel() {
        var tCorners : UIRectCorner = []
        if roundRightCorners {
            tCorners.insert(.topRight)
            tCorners.insert(.bottomRight)
        }
        if roundLeftCorners {
            tCorners.insert(.bottomLeft)
            tCorners.insert(.topLeft)
        }

        let path = UIBezierPath(roundedRect:self.bounds,
                                byRoundingCorners:tCorners,
                                cornerRadii: CGSize(width: cornerRadius, height:  cornerRadius))

        let maskLayer = CAShapeLayer()

        maskLayer.path = path.cgPath
        self.layer.mask = maskLayer
        self.layer.masksToBounds = true
    }

}

不在uistackview

时的视图

添加到 uistackview

时的视图

问题出在这一行:

let path = UIBezierPath(roundedRect:self.bounds,

self 实际上 正确的 bounds 之前,该行毫无意义。但是在 调用 drawTheLabel 的时候,它 还没有正确的 bounds。 (它可能是 1000x1000 或其他一些无意义的大小;您可以轻松 log/debug 并找出答案。)您正在调用 drawTheLabel 太快 ,在堆栈视图显示之前对其排列的子视图执行布局。

因此,您添加的遮罩对于最终尺寸的视图来说太大了,您只能看到遮罩的左上角;遮罩的其他角都偏向右侧和底部,对视图没有影响,因为它们不重叠。

您必须覆盖 layoutSubviews 并调用 super,然后 drawTheLabel()

这将在框架更改时应用圆角效果。