UITableView 中的自动布局在启动应用程序时和应用程序启动后的结果不同 运行
Result with auto layout in a UITableView different when starting the app and once the app is running
我有一个在 Interface Builder 中创建的 UITableView。里面是动态细胞。我添加了这样的约束(此方法在 tableView:cellForRowAtIndexPath
中调用):
@IBOutlet weak var rowView: UIView!
@IBOutlet weak var flagImageView: UIImageView!
@IBOutlet weak var computedRateLabel: UILabel!
@IBOutlet weak var historyButton: UIButton!
func buildConstraintsFor() {
let viewsDictionary = ["rowView": rowView, "flagImageView": flagImageView, "view1": computedRateLabel, "historyButton": historyButton]
rowView.layer.borderWidth = 1
flagImageView.layer.borderWidth = 1
computedRateLabel.layer.borderWidth = 1
historyButton.layer.borderWidth = 1
rowView.layer.borderColor = UIColor.blackColor().CGColor
flagImageView.layer.borderColor = UIColor.purpleColor().CGColor
computedRateLabel.layer.borderColor = UIColor.orangeColor().CGColor
historyButton.layer.borderColor = UIColor.greenColor().CGColor
// remove constraints
rowView.removeConstraints(rowView.constraints())
historyButton.removeConstraints(historyButton.constraints())
// add constraints
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[flagImageView]-[view1]-[historyButton]-|", options: nil, metrics: nil, views: viewsDictionary))
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-1-[flagImageView]-1-|", options: nil, metrics: nil, views: viewsDictionary))
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-1-[view1]-1-|", options: nil, metrics: nil, views: viewsDictionary))
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-1-[historyButton]-1-|", options: nil, metrics: nil, views: viewsDictionary))
// size
historyButton.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[historyButton(==25)]", options: nil, metrics: nil, views: viewsDictionary))
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[rowView(<=68)]", options: nil, metrics: nil, views: viewsDictionary))
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[rowView(>=67)]", options: nil, metrics: nil, views: viewsDictionary))
flagImageView.addConstraint(NSLayoutConstraint(item: flagImageView, attribute: .Width, relatedBy: .Equal, toItem: flagImageView, attribute: .Height, multiplier: 1, constant: 0))
}
当我 运行 应用程序时,我得到以下内容,这就是我想要的
当我滚动 TableView 并且当行消失并重新出现时(或者当我转到另一个 viewController 并返回时)我得到以下信息:
我不明白为什么。
如果我添加这个:
let width = UIScreen.mainScreen().applicationFrame.size.width
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[rowView(==\(width))]", options: nil, metrics: nil, views: viewsDictionary))
它似乎解决了问题,但当我横向时不再起作用。
是不是我做布局的时候做错了什么?
编辑:
当我在此处添加 rowView 的所有约束后打印它们的描述时,我得到的是:
<NSLayoutConstraint:0x17009f3b0 UIImageView:0x1701f5a00.leading == UITableViewCellContentView:0x1701968c0.leadingMargin>
<NSLayoutConstraint:0x17009f6d0 H:[UIImageView:0x1701f5a00]-(NSSpace(8))-[UILabel:0x13760f7f0'12 106,98']>
<NSLayoutConstraint:0x17009f9a0 H:[UILabel:0x13760f7f0'12 106,98']-(NSSpace(8))-[UIButton:0x137634b60]>
<NSLayoutConstraint:0x17009dec0 UITableViewCellContentView:0x1701968c0.trailingMargin == UIButton:0x137634b60.trailing>
<NSLayoutConstraint:0x170098920 V:|-(1)-[UIImageView:0x1701f5a00] (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x17009a4a0 V:[UIImageView:0x1701f5a00]-(1)-| (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x174098dd0 V:|-(1)-[UILabel:0x13760f7f0'12 106,98'] (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x174099550 V:[UILabel:0x13760f7f0'12 106,98']-(1)-| (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x170283c00 V:|-(1)-[UIButton:0x137634b60] (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x1702837a0 V:[UIButton:0x137634b60]-(1)-| (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x170283d90 V:[UITableViewCellContentView:0x1701968c0(<=68)]>
<NSLayoutConstraint:0x170283de0 V:[UITableViewCellContentView:0x1701968c0(>=67)]>
我 post 我找到的解决方案,因为它可能有帮助。感谢拉姆的帮助。
确实,当您以编程方式使用自动布局时,请不要忘记在要添加约束的每个组件上添加 setTranslatesAutoresizingMaskIntoConstraints(false)
。
在我的例子中,我已经在 Interface Builder 中创建了约束,并且由于我需要在 运行 期间从我的行中删除一个 UILabel,我不得不为我的行重新创建约束(例如方面比例、宽度或高度)。因此,由于我只想更改我的组件在我的行中的位置,所以我不需要为 flagImageView
或 historyButton
重新创建约束,只要我不删除它们即可。
但是我需要从我的 rowView
中删除约束,因为我正在添加新约束并删除一些约束。这个rowView
其实就是我UITableViewCell
的contentView
。通过删除约束,我也删除了链接到它的 superView 的约束,它实际上是 UITableViewCell
本身。所以我的 contentView
与其父项的大小不同。所以我只需要添加这两行:
rowView.superview?.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[rowView]-0-|", options: nil, metrics: nil, views: viewsDictionary))
rowView.superview?.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[rowView]-0-|", options: nil, metrics: nil, views: viewsDictionary))
我有一个在 Interface Builder 中创建的 UITableView。里面是动态细胞。我添加了这样的约束(此方法在 tableView:cellForRowAtIndexPath
中调用):
@IBOutlet weak var rowView: UIView!
@IBOutlet weak var flagImageView: UIImageView!
@IBOutlet weak var computedRateLabel: UILabel!
@IBOutlet weak var historyButton: UIButton!
func buildConstraintsFor() {
let viewsDictionary = ["rowView": rowView, "flagImageView": flagImageView, "view1": computedRateLabel, "historyButton": historyButton]
rowView.layer.borderWidth = 1
flagImageView.layer.borderWidth = 1
computedRateLabel.layer.borderWidth = 1
historyButton.layer.borderWidth = 1
rowView.layer.borderColor = UIColor.blackColor().CGColor
flagImageView.layer.borderColor = UIColor.purpleColor().CGColor
computedRateLabel.layer.borderColor = UIColor.orangeColor().CGColor
historyButton.layer.borderColor = UIColor.greenColor().CGColor
// remove constraints
rowView.removeConstraints(rowView.constraints())
historyButton.removeConstraints(historyButton.constraints())
// add constraints
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-[flagImageView]-[view1]-[historyButton]-|", options: nil, metrics: nil, views: viewsDictionary))
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-1-[flagImageView]-1-|", options: nil, metrics: nil, views: viewsDictionary))
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-1-[view1]-1-|", options: nil, metrics: nil, views: viewsDictionary))
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-1-[historyButton]-1-|", options: nil, metrics: nil, views: viewsDictionary))
// size
historyButton.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[historyButton(==25)]", options: nil, metrics: nil, views: viewsDictionary))
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[rowView(<=68)]", options: nil, metrics: nil, views: viewsDictionary))
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[rowView(>=67)]", options: nil, metrics: nil, views: viewsDictionary))
flagImageView.addConstraint(NSLayoutConstraint(item: flagImageView, attribute: .Width, relatedBy: .Equal, toItem: flagImageView, attribute: .Height, multiplier: 1, constant: 0))
}
当我 运行 应用程序时,我得到以下内容,这就是我想要的
当我滚动 TableView 并且当行消失并重新出现时(或者当我转到另一个 viewController 并返回时)我得到以下信息:
我不明白为什么。 如果我添加这个:
let width = UIScreen.mainScreen().applicationFrame.size.width
rowView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[rowView(==\(width))]", options: nil, metrics: nil, views: viewsDictionary))
它似乎解决了问题,但当我横向时不再起作用。
是不是我做布局的时候做错了什么?
编辑:
当我在此处添加 rowView 的所有约束后打印它们的描述时,我得到的是:
<NSLayoutConstraint:0x17009f3b0 UIImageView:0x1701f5a00.leading == UITableViewCellContentView:0x1701968c0.leadingMargin>
<NSLayoutConstraint:0x17009f6d0 H:[UIImageView:0x1701f5a00]-(NSSpace(8))-[UILabel:0x13760f7f0'12 106,98']>
<NSLayoutConstraint:0x17009f9a0 H:[UILabel:0x13760f7f0'12 106,98']-(NSSpace(8))-[UIButton:0x137634b60]>
<NSLayoutConstraint:0x17009dec0 UITableViewCellContentView:0x1701968c0.trailingMargin == UIButton:0x137634b60.trailing>
<NSLayoutConstraint:0x170098920 V:|-(1)-[UIImageView:0x1701f5a00] (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x17009a4a0 V:[UIImageView:0x1701f5a00]-(1)-| (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x174098dd0 V:|-(1)-[UILabel:0x13760f7f0'12 106,98'] (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x174099550 V:[UILabel:0x13760f7f0'12 106,98']-(1)-| (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x170283c00 V:|-(1)-[UIButton:0x137634b60] (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x1702837a0 V:[UIButton:0x137634b60]-(1)-| (Names: '|':UITableViewCellContentView:0x1701968c0 )>
<NSLayoutConstraint:0x170283d90 V:[UITableViewCellContentView:0x1701968c0(<=68)]>
<NSLayoutConstraint:0x170283de0 V:[UITableViewCellContentView:0x1701968c0(>=67)]>
我 post 我找到的解决方案,因为它可能有帮助。感谢拉姆的帮助。
确实,当您以编程方式使用自动布局时,请不要忘记在要添加约束的每个组件上添加 setTranslatesAutoresizingMaskIntoConstraints(false)
。
在我的例子中,我已经在 Interface Builder 中创建了约束,并且由于我需要在 运行 期间从我的行中删除一个 UILabel,我不得不为我的行重新创建约束(例如方面比例、宽度或高度)。因此,由于我只想更改我的组件在我的行中的位置,所以我不需要为 flagImageView
或 historyButton
重新创建约束,只要我不删除它们即可。
但是我需要从我的 rowView
中删除约束,因为我正在添加新约束并删除一些约束。这个rowView
其实就是我UITableViewCell
的contentView
。通过删除约束,我也删除了链接到它的 superView 的约束,它实际上是 UITableViewCell
本身。所以我的 contentView
与其父项的大小不同。所以我只需要添加这两行:
rowView.superview?.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[rowView]-0-|", options: nil, metrics: nil, views: viewsDictionary))
rowView.superview?.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[rowView]-0-|", options: nil, metrics: nil, views: viewsDictionary))