使用约束将UIView添加到TableViewCell中的ContentView

时间:2017-11-17 13:13:41

标签: ios

我正在尝试使用Constraints将单元格添加到UITableView。你知不知道怎么。以下是:

enter image description here

并说:UIView的高度不明确

您知道如何使用约束将UIView添加到ContextView - 请注意约束中的固定高度。

import UIKit

class ViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier:"Cell")
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")

        if cell == nil {
            cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
        }

        let view = UIView(frame: cell!.frame)
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = UIColor.orange

        let constraintTop = NSLayoutConstraint(item: cell!.contentView,
                                               attribute: NSLayoutAttribute.top,
                                               relatedBy: NSLayoutRelation.equal,
                                               toItem: view,
                                               attribute: NSLayoutAttribute.top,
                                               multiplier: 1,
                                               constant: 0)

        let constraintLeading = NSLayoutConstraint(item: cell!.contentView,
                                                   attribute: NSLayoutAttribute.leading,
                                                   relatedBy: NSLayoutRelation.equal,
                                                   toItem: view,
                                                   attribute: NSLayoutAttribute.leading,
                                                   multiplier: 1,
                                                   constant: 0)

        let constraintTrailing = NSLayoutConstraint(item: cell!.contentView,
                                                    attribute: NSLayoutAttribute.trailing,
                                                    relatedBy: NSLayoutRelation.equal,
                                                    toItem: view,
                                                    attribute: NSLayoutAttribute.trailing,
                                                    multiplier: 1,
                                                    constant: 0)

        let constraintHeight = NSLayoutConstraint(item: cell!.contentView,
                                                  attribute: NSLayoutAttribute.height,
                                                  relatedBy: NSLayoutRelation.equal,
                                                  toItem: nil,
                                                  attribute: NSLayoutAttribute.height,
                                                  multiplier: 1, constant: 50) // << Note fixed height

        view.translatesAutoresizingMaskIntoConstraints = false

        cell?.contentView.addSubview(view)
        cell?.contentView.addConstraints([constraintTop, constraintLeading, constraintTrailing, constraintHeight])

        return cell!
    }


}

尝试更改约束以包含contentView的底部:

import UIKit

class ViewController: UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier:"Cell")
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")

        if cell == nil {
            cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
        }

        let view = UIView(frame: cell!.frame)
        view.translatesAutoresizingMaskIntoConstraints = false
        view.backgroundColor = UIColor.orange

        let constraintTop = NSLayoutConstraint(item: cell!.contentView,
                                               attribute: NSLayoutAttribute.top,
                                               relatedBy: NSLayoutRelation.equal,
                                               toItem: view,
                                               attribute: NSLayoutAttribute.top,
                                               multiplier: 1,
                                               constant: 0)

        let constraintLeading = NSLayoutConstraint(item: cell!.contentView,
                                                   attribute: NSLayoutAttribute.leading,
                                                   relatedBy: NSLayoutRelation.equal,
                                                   toItem: view,
                                                   attribute: NSLayoutAttribute.leading,
                                                   multiplier: 1,
                                                   constant: 0)

        let constraintTrailing = NSLayoutConstraint(item: cell!.contentView,
                                                    attribute: NSLayoutAttribute.trailing,
                                                    relatedBy: NSLayoutRelation.equal,
                                                    toItem: view,
                                                    attribute: NSLayoutAttribute.trailing,
                                                    multiplier: 1,
                                                    constant: 0)

        let constraintBottom = NSLayoutConstraint(item: cell!.contentView,
                                                  attribute: NSLayoutAttribute.bottom,
                                                  relatedBy: NSLayoutRelation.equal,
                                                  toItem: view,
                                                  attribute: NSLayoutAttribute.bottom,
                                                  multiplier: 1, constant: 0)

        view.translatesAutoresizingMaskIntoConstraints = false
        cell?.contentView.translatesAutoresizingMaskIntoConstraints = false
        cell?.contentView.addSubview(view)
        cell?.contentView.addConstraints([constraintTop, constraintLeading, constraintTrailing, constraintBottom])

        return cell!
    }


}

3 个答案:

答案 0 :(得分:2)

你做错了几件事。

首先,您要向后设置约束。您希望将新<draggable v-if="element.notes" class="list-group" element="ul" :options="dragOptions" :move="onMove" :list="element.notes"> 限制为view

contentView

其次,不要这样做:

let constraintTop = NSLayoutConstraint(item: view,  // constrain this view
                           attribute: NSLayoutAttribute.top,
                           relatedBy: NSLayoutRelation.equal,
                           toItem: cell?.contentView,  // to this view
                           attribute: NSLayoutAttribute.top,
                           multiplier: 1,
                           constant: 0)

第三,你的代码是(好吧,将)添加一个新的&#34;橙色视图&#34;每次重复使用细胞。在自定义单元格类的init部分中添加子视图要好得多,但如果您要在cell?.contentView.translatesAutoresizingMaskIntoConstraints = false 中执行此操作,请先检查它是否已经存在:

cellForRow

第四,你可能会发现以这种方式添加约束更容易/更合乎逻辑/更清洁/等等:

    if cell.contentView.subviews.count == 0 {
        // no, so add it here

        let view = UIView()

        // continue with view setup

并且......因为您已经注册了一个单元格类以供重用,所以这种格式将为您提供一个有效的单元格:

cell.contentView.addSubview(view)

view.topAnchor.constraint(equalTo: cell.contentView.topAnchor, constant: 0.0).isActive = true
view.bottomAnchor.constraint(equalTo: cell.contentView.bottomAnchor, constant: 0.0).isActive = true
view.leadingAnchor.constraint(equalTo: cell.contentView.leadingAnchor, constant: 0.0).isActive = true
view.trailingAnchor.constraint(equalTo: cell.contentView.trailingAnchor, constant: 0.0).isActive = true

所以,这是完整的功能:

    // instead of this
    //var cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
    //if cell == nil {
    //  cell = UITableViewCell(style: .default, reuseIdentifier: "Cell")
    //}

    // better method
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

答案 1 :(得分:1)

您的第四个约束是对contentView应用固定高度。你想要的是固定contentView的底边和你的自定义view(就像你使用前导/顶部/尾部一样)将恒定高度约束应用于{{1} },而不是viewcontentView只是简单地适应其子视图,你不直接告诉它它的高度。

此外,在您的contentView中,您需要设置viewDidLoad,因为您是通过约束计算高度的。

此外,您将遇到问题,因为此代码位于tableView.rowHeight = UITableViewAutomaticDimension。每当新单元格出现在屏幕上时,都会调用此函数,这意味着在滚动时,您将重用相同的视图并添加重复的额外视图。我建议您继承cellForRow子类并将此代码放在UITableViewCell

答案 2 :(得分:0)

嗯,解决方法是:阅读“输出”!

Changing the translatesAutoresizingMaskIntoConstraints property of the contentView of a UITableViewCell is not supported and will result in undefined behavior, as this property is managed by the owning UITableViewCell

让以下内容搞砸了:

cell?.contentView.translatesAutoresizingMaskIntoConstraints = false

删除此行,它将起作用。