UIView子自动帧大小

Posted

技术标签:

【中文标题】UIView子自动帧大小【英文标题】:UIView child automatic frame size 【发布时间】:2018-07-25 08:23:06 【问题描述】:

我正在尝试将自定义 UIView (LabelIcon) 添加到父视图,它不应该关心孩子的大小 - 他应该根据孩子的高度将它们以全宽堆叠在彼此下方(这会有所不同)。

目前这是我在父级中添加子级的方式:

    let locationLabel = LabelIcon(frame: .zero, icon: "location", text: "Lane\nlane")
    let locationLabel2 = LabelIcon(frame: .zero, icon: "location", text: "Second text line\nLine line line\nAnother line\nsome more line")
    content.addSubview(locationLabel)
    content.addSubview(locationLabel2)

(我不想在这里手动设置框架 - 应该是自动的)

这些视图的约束,因此它们至少以某种方式可见(因为我没有设置框架):

    locationLabel.snp.makeConstraints  (make) in
        make.top.left.right.equalToSuperview()
        make.height.equalTo(40)
    

    locationLabel2.snp.makeConstraints  (make) in
        make.left.right.equalToSuperview()
        make.top.equalTo(locationLabel.snp.bottom)
        make.height.equalTo(40)
    

这可行,但对每个元素都这样做会很痛苦。另外我现在不知道内部元素的高度。

我想要实现的是不必在父级中定义任何硬编码约束。子视图应该自己决定它的高度。

孩子是这样定义的:

class LabelIcon: UIView 

    init(frame: CGRect, icon: String, text: String) 
        super.init(frame: frame)

        self.backgroundColor = UIColor.orange

        let iconImageView = UIImageView(image: UIImage(named: icon))
        iconImageView.contentMode = UIViewContentMode.scaleAspectFit
        self.addSubview(iconImageView)


        let label = UILabel()
        label.textAlignment = .left
        label.numberOfLines = 0
        label.text = text
        self.addSubview(label)

        iconImageView.snp.makeConstraints  (make) in
            make.top.equalToSuperview().offset(5)
            make.left.equalToSuperview().offset(10)
        

        label.snp.makeConstraints  (make) in
            make.top.equalToSuperview()
            make.left.equalTo(iconImageView.snp.right).offset(20)

        
    

    required init?(coder aDecoder: NSCoder) 
        fatalError("init(coder:) has not been implemented")
    

我怎样才能以一种知道父级宽度的方式定义子级,但高度将根据标签大小自动完成?文本将具有动态行数。

在父级中会有很多这样的视图,因此我希望有尽可能少的约束(不要为每个 LabelIcon 实例手动执行)。

根据这段代码,这是当前状态:

我所有的视图都是通过自动布局以编程方式完成的(使用 SnapKit,没有故事板或 xib)。我想使用 UIStackView,但无论如何孩子必须定义高度才能工作。

编辑: 使用这些约束时,视图本身是可见的:

locationLabel.snp.makeConstraints  (make) in
    make.top.left.right.equalToSuperview()


locationLabel2.snp.makeConstraints  (make) in
    make.left.right.equalToSuperview()
    make.top.equalTo(locationLabel.snp.bottom)

但视图相互重叠(标签 2 不在标签下方)。此外,视图的尺寸基本上为 0,0 - 没有橙色背景:

来自接受的答案:

标签约束:

label.snp.makeConstraints  (make) in
    make.top.equalToSuperview()
    make.left.equalTo(iconImageView.snp.right).offset(20)
    make.bottom.equalToSuperview().offset(-10)
    make.right.equalToSuperview().offset(-10)

家长:

locationLabel.snp.makeConstraints  (make) in
    make.top.left.equalToSuperview()


locationLabel2.snp.makeConstraints  (make) in
    make.left.equalToSuperview()
    make.top.equalTo(locationLabel.snp.bottom)

结果:

【问题讨论】:

【参考方案1】:

视图的内部标签添加这样的底部约束

 make.bottom.equalToSuperview().offset(10)

//

添加右约束

make.right.equalToSuperview().offset(10)

移除任何静态高度

make.height.equalTo(40)

然后视图应该根据文本调整大小,想法是通过静态值或左&&右值给标签一个宽度

【讨论】:

更新:label.snp.makeConstraints (make) in make.top.equalToSuperview() make.left.equalTo(iconImageView.snp.right).offset(20) make.bottom.equalToSuperview( ).offset(-10) make.right.equalToSuperview().offset(-10) 和父级: locationLabel.snp.makeConstraints (make) in make.top.left.equalToSuperview() locationLabel2.snp.makeConstraints (make) in make.left.equalToSuperview() make.top.equalTo(locationLabel.snp.bottom) 谢谢!

以上是关于UIView子自动帧大小的主要内容,如果未能解决你的问题,请参考以下文章

自动布局:ViewDidAppear 中的帧大小不正确

UIView 使用自动布局调整大小,但在运行时获取其帧大小不正确 ios

UIView 子视图不是为 iPad 自动旋转或自动调整大小

创建一个基于 UIView 的子视图自动调整大小的视图

根据设备方向在 alloc/init 上设置正确的 UIView 帧大小

使用固定大小的子视图和自动布局调整 UIView 的大小不起作用