展开和收缩标签在UITableViewCell中不起作用

时间:2018-09-02 00:16:53

标签: ios swift

我正在尝试使用UITableView并具有将在用户单击标签时扩展或收缩的单元格内容。

但是,我看到的行为是单元格将收缩(例如,我将标签的numberOfLines从0更改为1,然后标签将收缩)。但是,当我将标签的numberOfLines从1更改为0时,它不会扩展。

我整理了一个简单的测试程序来显示我遇到的问题。

我正在使用UITapGestureRecognizer来处理标签的轻击事件,这就是我扩展或收缩标签的地方。有人知道我在做什么错吗?

这是我的情节提要和视图控制器代码。

enter image description here

import UIKit

class MyCell : UITableViewCell {

    @IBOutlet weak var myLabel: UILabel!
}

class TableViewController: UITableViewController {

    let cellID = "cell"

    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.rowHeight = UITableViewAutomaticDimension
        self.tableView.estimatedRowHeight = 75

    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 12
    }

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "section " + String(section)
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return 4
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: self.cellID, for: indexPath) as! MyCell

        cell.myLabel.isUserInteractionEnabled = true
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.handleCellTapped(_:)))
        cell.myLabel!.addGestureRecognizer(tapGesture)

        // Configure the cell...
        if indexPath.row % 2 == 0 {
            cell.myLabel?.numberOfLines = 1
            cell.myLabel.text = "This is some long text that should be truncated.  It should not span over multiple lines. Let's hope this actually works. \(indexPath.row)"
        } else {
            cell.myLabel?.numberOfLines = 0
            cell.myLabel.text = "This is some really, really long text.  It should span over multiple lines. Let's hope this actually works. \(indexPath.row)"
        }

        return cell
    }

    @objc func handleCellTapped(_ sender: UITapGestureRecognizer) {
        print("Inside handleCellTapped...")
        guard let label = (sender.view as? UILabel) else { return }

        //label.translatesAutoresizingMaskIntoConstraints = false

        // expand or contract the cell accordingly
        if label.numberOfLines == 0 {
            label.numberOfLines = 1
        } else {
            label.numberOfLines = 0
        }
    }
}

3 个答案:

答案 0 :(得分:2)

做两件事。

  1. 设置垂直内容包含优先级,然后 将标签的垂直内容压缩优先级设置为1000。
  2. 更改Label的行数后,调用 tableView.beginUpdates() tableView.endUpdates()

这肯定可以工作。

答案 1 :(得分:1)

尝试

tableView.beginUpdates()
if label.numberOfLines == 0 {
    label.numberOfLines = 1
} else {
    label.numberOfLines = 0
}
tableView.endUpdates()

答案 2 :(得分:1)

您几乎明白了,但这是您应该注意的几件事。

首先,通过label处理UIGestureRecognizer,这是相当大的开销。为此,UITableViewDelegate有自己的方法:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)

其次,由于以下原因,您正在使用自动调整大小的单元格

self.tableView.rowHeight = UITableViewAutomaticDimension
self.tableView.estimatedRowHeight = 75

有一个重要的规则:您应将myLabel固定在超级视图的每一侧(请参阅official docs为何):

enter image description here

最后一步,当numberOfLines更改时,您应该为cell设置高度(展开或折叠)动画,而无需重新加载单元格:

tableView.beginUpdates()
tableView.endUpdates()

Docs

  

您还可以在不重新加载单元格的情况下,使用此方法以及endUpdates()方法为行高设置动画效果。


完整代码:

class MyCell: UITableViewCell {
    @IBOutlet weak var myLabel: UILabel!
}

class TableViewController: UITableViewController {

    let cellID = "cell"

    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.rowHeight = UITableViewAutomaticDimension
        self.tableView.estimatedRowHeight = 75
    }

    // MARK: - Table view data source

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

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        return "section " + String(section)
    }

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: self.cellID, for: indexPath) as! MyCell
        cell.selectionStyle = .none // remove if you need cell selection

        if indexPath.row % 2 == 0 {
            cell.myLabel?.numberOfLines = 1
            cell.myLabel.text = "This is some long text that should be truncated.  It should not span over multiple lines. Let's hope this actually works. \(indexPath.row)"
        } else {
            cell.myLabel?.numberOfLines = 0
            cell.myLabel.text = "This is some really, really long text.  It should span over multiple lines. Let's hope this actually works. \(indexPath.row)"
        }

        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: false)

        guard let cell = tableView.cellForRow(at: indexPath) as? MyCell else { return }

        cell.myLabel.numberOfLines = cell.myLabel.numberOfLines == 0 ? 1 : 0

        tableView.beginUpdates()
        tableView.endUpdates()
    }

}