将 xib 文件中的视图添加到 UITableViewCell 添加约束

Posted

技术标签:

【中文标题】将 xib 文件中的视图添加到 UITableViewCell 添加约束【英文标题】:Add a view from a xib file to a UITableViewCell adding constraints 【发布时间】:2015-12-20 09:44:57 【问题描述】:

我创建了一个带有自定义视图的 xib 文件,我想在 UITableViewCell 中显示该文件。

问题是:在 xib 文件中,我将 UIView 的宽度设置为 600(sizeFreeform)但我想使用约束来获得每个设备的正确宽度。

我在UITableViewCelladdSubview() 中添加了这个视图,所以我认为这个视图必须约束到单元格的视图,对吗?我该怎么做?

我添加了一些代码:

这是我自定义的UIView 与 xib 文件相关:

class DownloadView: UIView, NSURLSessionDownloadDelegate

///utilizzata per mostrare il nome del file in download
@IBOutlet var nomeFileInDownloadLabel: UILabel!

///utilizzata per mostrare la percentuale di download completato
@IBOutlet var quantitaScaricataLabel: UILabel!

///utilizzata per mostrare il download
@IBOutlet var progressView: UIProgressView!

var view : UIView!

private var downloadTask: NSURLSessionDownloadTask?

//Initialization
override init(frame: CGRect) 
    super.init(frame: frame)
    xibSetup()


required init(coder aDecoder: NSCoder) 
    super.init(coder: aDecoder)!



//I setup the xib from here
func xibSetup() 
    view = loadViewFromNib()

    //if I set the following one the view is a square
    //view.frame = bounds

    // Make the view stretch with containing view
    view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
    self.addSubview(view)


//I load the xib file
func loadViewFromNib() -> UIView 

    let bundle = NSBundle(forClass: self.dynamicType)
    let nib = UINib(nibName: "View", bundle: bundle)
    let view = nib.instantiateWithOwner(self, options: nil)[0] as! UIView
    return view

//some code for other task 
...

在我的UITableView 方法tableView(tableView:cellForRowAtIndexPath) 中添加视图:

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCellWithIdentifier("DownloadRootTVC_IDcell", forIndexPath: indexPath) as! DownloadTVCell

    //I get my custom view from an array
    let myView = self.listOfViewsDownlaod[indexPath.row]

    //I add the view to the cell
    cell.addSubview(myView)


    return cell

在最后一种方法中,我认为我必须设置约束以适应 UITableViewCell 中的自定义视图,使其适应设备宽度。

编辑:

由于我想使子视图的宽度和高度适应单元格,所以我写了这个:

    let topConstraint = NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: cell, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 8)
    cell.addConstraint(topConstraint)

    let bottomConstraint = NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: cell, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 8)
    cell.addConstraint(bottomConstraint)

    let leftConstraint = NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.Left, relatedBy: NSLayoutRelation.Equal, toItem: cell, attribute: NSLayoutAttribute.Left, multiplier: 1, constant: 20)
    cell.addConstraint(leftConstraint)

    let rightConstraint = NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.TrailingMargin, relatedBy: NSLayoutRelation.Equal, toItem: cell, attribute: NSLayoutAttribute.TrailingMargin, multiplier: 1, constant: 20)
    cell.addConstraint(rightConstraint)

唯一不起作用的是正确的,视图继续在屏幕上。我也尝试使用NSLayoutAttribute.RightNSLayoutAttribute.RighMargin 或将常量设置为负值,但不起作用。

【问题讨论】:

【参考方案1】:

当您将其添加为子视图时,您的 xib 视图对其父视图没有任何限制。您应该以编程方式创建它们。 There is 一个很好的例子。例如,如果你想把你的视图放在超级视图的中心并且大小相同,你可以写下一个:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell 

  let cell = tableView.dequeueReusableCellWithIdentifier("cell")!
  let myView = UIView()
  myView.backgroundColor = UIColor.redColor()
  myView.translatesAutoresizingMaskIntoConstraints = false
  cell.addSubview(myView)
  let horizontalConstraint = NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.CenterX, relatedBy: NSLayoutRelation.Equal, toItem: cell, attribute: NSLayoutAttribute.CenterX, multiplier: 1, constant: 0)
  cell.addConstraint(horizontalConstraint)

  let verticalConstraint = NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: cell, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0)
  cell.addConstraint(verticalConstraint)

  let widthConstraint = NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: cell, attribute: NSLayoutAttribute.Width, multiplier: 1, constant: 0)
  cell.addConstraint(widthConstraint)

  let heightConstraint = NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: cell, attribute: NSLayoutAttribute.Height, multiplier: 1, constant: 0)
  cell.addConstraint(heightConstraint)
  return cell

它看起来像这样(蓝色 - tableView,红色 - myView):

【讨论】:

感谢您的帮助。不幸的是,由于这些限制导致应用程序崩溃,我将学习如何使用它们以便正确使用它们。谢谢 @Ernesto,好的,也许您可​​以显示您的错误,我会尽力提供帮助? 我收到这个错误:Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** +[NSLayoutConstraint constraintWithItem:attribute:relatedBy:toItem:attribute:multiplier:constant:]: Unknown layout attribute' 你怎么看?非常感谢!! @Ernesto,是的,对不起。我的错。宽度和高度约束的 NSLayoutAttribute 不应该是 .NotAnAttribute。我更新了我的答案。 好的,谢谢!今天晚上我会试试新代码。我会告诉你的【参考方案2】:

终于找到问题了:

问题出在xibSetup() 方法中,因为我加载了xib 但我没有设置约束!所以我的新方法是:

func xibSetup() 
    let myView = loadViewFromNib()

    myView.translatesAutoresizingMaskIntoConstraints = false

    self.addSubview(myView)

    let leading = NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.Leading, relatedBy: NSLayoutRelation.Equal, toItem: myView.superview, attribute: NSLayoutAttribute.Leading, multiplier: 1, constant: 0)
    self.addConstraint(leading)

    let bottom = NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: myView.superview, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0)
    self.addConstraint(bottom)

    let trailing = NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.Trailing, relatedBy: NSLayoutRelation.Equal, toItem: myView.superview, attribute: NSLayoutAttribute.Trailing, multiplier: 1, constant: 0)
    self.addConstraint(trailing)

    let top = NSLayoutConstraint(item: myView, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: myView.superview, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0)
    self.addConstraint(top)


这解决了我的问题。

【讨论】:

以上是关于将 xib 文件中的视图添加到 UITableViewCell 添加约束的主要内容,如果未能解决你的问题,请参考以下文章

将 xib 中的子视图添加到自定义 UIView

如何将 UITableView 作为子视图添加到 xib 中的 UIView?

将子视图添加到 xib 文件

将 SpriteKit 视图集成到 xib 视图中

如何为不同的xib添加一个共同的视图?

将 XIB 的 UIScrollView 添加到视图时设置 contentSize