SnapKit:如何以编程方式设置TableViewCell中项目的布局约束

时间:2019-02-24 12:16:28

标签: ios swift xcode autolayout

我是swift / iOS开发人员的初学者。来自Web开发人员的布局模型与DOM / Box模型相比完全让我感到困惑。我知道这意味着要全神贯注,但是对于我的一生,我似乎无法弄清楚,我希望像这样的基本示例可以帮助说明一些事情,即使我正在使用DSL。像snapkit:http://snapkit.io/

我该如何为以下布局建立约束:

diagram

我到目前为止所拥有的-显然-错误的是以下内容:

label1.snp.makeConstraints { (make) -> Void in
  make.leading.equalTo(Style.MARGIN)
  make.trailing.equalTo(-Style.MARGIN)
  make.centerX.equalTo(self)
  make.top.equalTo(Style.MARGIN)
}

label2.snp.makeConstraints { (make) -> Void in
  make.leading.equalTo(Style.MARGIN)
  make.trailing.equalTo(-Style.MARGIN)
  make.centerX.equalTo(self)
  make.top.equalTo(label1.snp.bottom)
}

exampleImage.snp.makeConstraints { (make) -> Void in
  make.leading.equalTo(0)
  make.trailing.equalTo(0)
  make.top.equalTo(label2.snp.bottom).offset(Style.MARGIN)
  make.bottom.equalTo(0)
}

其中Style.MARGIN只是设置为20的常量

我觉得我只需要看一个这样的例子就可以了解布局的流程和构建方式,也许可以像构建一个网站那样摆脱它的困扰。 从最基本的角度来看,我最困惑的事情是了解如何将动态高度不同的对象放置在上一个对象的下面,并使tableViewCell也相应地调整大小。

2 个答案:

答案 0 :(得分:1)

自iOS 9开始,可以使用UIStackViews构建许多类似这样的简单布局,UIStackViews是管理子视图及其布局约束的容器视图,因此您不必(例如怀旧评论家)。

除了概念上简单之外,UIStackViews还具有许多好处。它们性能良好,易于使用,并且易于隐藏/显示视图,而无需手动操作和更新很多约束。

在这种情况下,您有两个UILabel和一个UIImageView以一定的间距彼此堆叠。如果要实现此布局,则可以将两个标签组合在一个UIStackView中,将其添加到具有一些插图的UIView中,然后将该视图与UIImageView一起添加到另一个UIStackView中,如下所示:

  

UIStackView(1)

     
    

UIView(2)

         
      

UIStackView(3)

             
        

UILabel(4)

                 

UILabel(5)

      
    
         

UIImageView(6)

  

在代码中:

let containerStackView = UIStackView() // (1)
containerStackView.axis = .vertical

let greenLabel = UILabel() // (4)
greenLabel.text = "Hello,"

let blueLabel = UILabel() // (5)
blueLabel.text = "World!"

let textStackView = UIStackView() // (3)
textStackView.axis = .vertical
textStackView.spacing = 10
textStackView.addArrangedSubview(greenLabel)
textStackView.addArrangedSubview(blueLabel)

let textContainerView = UIView() // (2)
textContainerView.addSubview(textStackView)
textStackView.snp.makeConstraints { make in
    make.edges.equalToSuperview().inset(20)
}

let imageView = UIImageView(image: UIImage(named: "my-image") // (6)
containerStackView.addArrangedSubview(textContainerView)
containerStackView.addArrangedSubview(imageView)

然后您需要将容器堆栈视图限制为UITableViewCell的内容视图:

contentView.addSubview(containerStackView)
containerStackView.snp.makeConstraints { make in
    make.edges.equalToSuperview()
}

这就是我要做的。当然,您自己管理约束的方法同样有效,并且可以按照以下步骤进行:

contentView.addSubview(label1)
label1.snp.makeConstraints { make in
    make.leading.equalToSuperview().offset(20)
    make.trailing.equalToSuperview().offset(-20)
    make.top.equalToSuperview().offset(20)
}

contentView.addSubview(label2)
label2.snp.makeConstraints { make in
    make.leading.equalToSuperview().offset(20)
    make.trailing.equalToSuperview().offset(-20)
    make.top.equalTo(label1.snp.bottom).offset(10)
}

contentView.addSubview(exampleImage)
exampleImage.snp.makeConstraints { make in
    make.leading.trailing.bottom.equalToSuperview()
    make.top.equalTo(label2.snp.bottom).offset(20)
}

请注意,我是在文本编辑器中编写的,因此可能会有一些错别字,但总体思路应该成立。

答案 1 :(得分:0)

以下是添加约束时您必须直接或间接指定的事物的列表:

  • X位置
  • Y位置
  • 宽度
  • 高度

在进行约束时思考每件事都可以使事情变得非常简单。

首先,label1

  1. X位置:我们希望它水平居中
  2. Y位置:超级视图顶部20个
  3. 宽度:某个数字,以使它的左边距超级视图的左边20,而右边距超级视图的右边20,这也表示X位置
  4. 高度:您尚未在屏幕截图中指定此高度。我假设您希望其高度为超级视图的1/3

这转化为以下约束:

make.topMargin.equalTo(20)
make.leftMargin.equalTo(20)
make.rightMargin.equalTo(-20)
make.height.equalToSuperview().dividedBy(3)

现在为label2

  1. X位置:我们希望它水平居中
  2. Y位置:从label1的底部起10个
  3. 宽度:某个数字,以使它的左边距超级视图的左边20,而右边距超级视图的右边20,这也暗示了它的X位置
  4. 高度:一些数字,它距超级视图的底部20个距离

这意味着:

make.top.equalTo(label1.snp.bottom).offset(10)
make.leftMargin.equalTo(20)
make.rightMargin.equalTo(-20)
make.bottomMargin.equalTo(-20)

您也可以使用UIStackView来实现。

有关如何使表格视图根据内容调整其单元格高度的信息,请参见this