Swift 具有自动布局的 UIView 子类

Swift UIView subclass with auto layout

我正在创建一个新的自定义 UIView 子类,我想在其中为该视图使用自动布局。该视图包含一个标签。我的自定义视图应根据文本大小自动调整大小。我的困惑是,这是否有效,我是否必须使用框架初始化我的自定义视图?

class CustomView : UIView
{
    var label : UILabel = UILabel()
    
    var text : String = ""
    
    init(text: String)
    {
        super.init(frame: .zero)

        self.text = text
        
        setupView()
        setupLayout()
    }

    required init(coder aDecoder: NSCoder) {
        fatalError("This class does not support NSCoding")
    }
    
    func setupView() -> Void
    {
        self.backgroundColor = UIColor(red: 85.0/255.0, green: 88.0/255.0, blue: 91.0/255.0, alpha: 1.0)
        
        //Create main label
        let label = UILabel()
        label.text = self.text
        label.textColor = .white
        label.font = label.font.withSize(12.0)
        label.lineBreakMode = .byWordWrapping
        label.numberOfLines = 0
        label.textAlignment = .left
        self.label = label
        addSubview(label)
    }
    

    override class var requiresConstraintBasedLayout: Bool {
        return true
    }
    
    func setupLayout() -> Void
    {
        label.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            label.topAnchor.constraint(equalTo: topAnchor),
            label.bottomAnchor.constraint(equalTo: bottomAnchor),
            label.trailingAnchor.constraint(equalTo: trailingAnchor),
            label.leadingAnchor.constraint(equalTo: leadingAnchor),
            widthAnchor.constraint(equalToConstant: 200),
            heightAnchor.constraint(equalToConstant: 200)
        ])
    }
}

这是我尝试过的。我创建了一个自己的 init() 方法,我将零帧传递给超级初始化。那是对的吗?我希望根据文本通过自动布局来完成大小。或者我是否需要在使用 CustomView 的父视图中设置约束。

自定义视图的初始帧设置为.zero就可以了。

如果您想实现 auto-sizing 自定义视图,并且在您的情况下,标签指示了所需的视图大小,您可以利用标签的 intrinsicContentSize 并将其设置为您的容器视图。

override var intrinsicContentSize: CGSize {
    label.intrinsicContentSize
}

这样,您需要做的就是在创建自定义视图时设置 origin。其余的将由 AutoLayout 自动管理。此外,例如,当您将自定义视图添加到 UIStackView 时,您甚至不需要设置原点。换句话说,您的视图现在就像一个 UILabel。

也就是说,您现在可以安全地删除 UILabel 的不必要约束,让超级视图处理其余部分:

label.translatesAutoresizingMaskIntoConstraints = false
    
    NSLayoutConstraint.activate([
        label.topAnchor.constraint(equalTo: topAnchor),
        label.leadingAnchor.constraint(equalTo: leadingAnchor)
    ])

为什么要给标签 heightAnchor?

如果您希望它根据文本自动调整大小,您只需:

  1. 标签的行数为 0
  2. 将标签的顶部、前导、底部和尾部锚点提供给其超级视图
  3. 超级视图至少应该有顶部、前导和尾随锚点到它的超级视图(视图控制器视图),您将在其中添加此自定义视图。

初始化自定义视图时不要忘记将 属性 translatesAutoresizingMaskIntoConstraints 设置为 false