类似于 UILabel 的自动布局中自定义视图的 Storyboard 设置宽度/高度

Storyboard Set Width / Height for Custom View in Autolayout Similar to UILabel

标签在 iOS autolayout 中非常方便,因为它们不需要 constraints 来确定大小,它们只需要 X 和 Y 位置。对于静态文本,这很棒。

我有一个自定义视图,我想为自动布局提供一个默认大小,类似于 UILabels。这可能吗?我熟悉 IBInspectableIBDesignable,但我不确定如何实现它。我在 storyboards 中使用 autolayout,但我认为该解决方案适用于 storyboards + 程序化。

我知道我可以只设置 heightwidth,但这是将在任何地方使用的视图,所以最好有 width / height动态。

您可以覆盖

var intrinsicContentSize: CGSize { get }
UIView 的

属性 并根据其内容计算和 return 视图的高度和宽度。

参考:intrinsicContentSize

不幸的是,如果不指定其大小值,即 widthheight.

,则无法顺利添加 UIView

说到自动布局,您有 2 个选项,可能您也已经知道了。 1) 您应该设置 UIView's 大小值,或者 2. 您设置其他 UI 对象的大小以便自动布局可以理解 UIView.

的大小

在编程方面,在创建 UIView 对象时,如果您不提供框架,则不会显示。虽然这可能是一个可以放置在任何位置、任何大小的解决方案,但当您使用 xib 或故事板时,它可能并不理想,因为这些接口上会有间隙,这也可能会混淆开发。

我考虑的方式包括同时使用 intrinsicContentSizeIBDesignable。我为此做了一个小演示,您可以在下面找到这段代码。我将分享 2 个示例,一个继承自 UILabel,另一个继承自 UIView,以便我可以更轻松地展示 intrinsicContentSize 的用法。

下面是 UIView 一个。

import UIKit

@IBDesignable class UIDemoView: UIView {

    func setup() {
        layer.cornerRadius = frame.height / 5
        clipsToBounds = true
    }    

    override func awakeFromNib() {
        super.awakeFromNib()
        self.setup()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        self.setup()
    }

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        self.setup()
    }

    override var intrinsicContentSize: CGSize {
        let newWidth = 100
        let newHeight = 100
        let newSize = CGSize(width: newWidth, height: newHeight)
        return newSize
    }
}

下面是UI标签。

import UIKit

@IBDesignable class UIDemoLabel: UILabel {

    func setup() {
        layer.cornerRadius = frame.height / 2
        clipsToBounds = true
        textAlignment = .center
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        self.setup()
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        self.setup()
    }

    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        self.setup()
    }

    override var intrinsicContentSize: CGSize {
        let superSize = super.intrinsicContentSize
        let newWidth = superSize.width + superSize.height
        let newHeight = superSize.height
        let newSize = CGSize(width: newWidth, height: newHeight)
        return newSize
    }
}

这是自动布局的输出

我特意展示了两个对象的约束,所以你可以检查我是否理解正确。它们都只有 2 个约束:顶部对齐和居中对齐。

UILabels 有它们自己的 intrinsicContentSize,所以当覆盖它们时,我们可以使用它们已经给定的 intrinsicContentSize 作为参考,作为我们想做的任何事情的指导。 UIViews intrinsicContentSize 没有设置,因此我们必须想办法给它们特定的尺寸。由于不确定,我猜测 UILabel intrinsicContentSize 实现,逻辑很可能与文本的大小有关。您可以像上面的代码一样简单地传递常量,也可以使用任何自定义逻辑来提供 CGFloats

只是我的一个想法:尽管我提出了这个解决方案,但我并不喜欢 IBDesignables。从我的角度来看,他们放慢了开发速度,因为它存在缺陷。因此,老实说,我宁愿 1. 将 UIView 对象放在 xibs 和 storyboards 上,2. 将其 class 从 UIView 更改为自定义 UIView class,3. 设置其约束,4. 从其 IBOutlet 以编程方式设置剩余属性。这是更传统的方式,不过:)

希望对您有所帮助!