如何在tableview willDisplay函数中更改布局和属性设置?

时间:2018-12-27 03:05:37

标签: ios swift uitableview

我有一个问题。
我有一个UITableView和一个自定义UITableViewCell。
首先,我将检查自定义UITableViewCell中的UILabel是否被截断。 如果UILabel被截断,我将向UIButton显示“显示更多”,并将UILabel numberOfLines设置为等于2。
单击“显示更多” UIButton时,将UILabel numberOfLines设置为0,并且UIButton标题更改为“关闭”。
UITableViewCell的高度增加了UILabel内容的扩展。
如果不对UILabel进行截断,则不显示UIButton并将UILabel numberOfLines设置为0。
UITableViewCell的高度也增加了UILabel内容的扩展。
如何实现这种情况?
谢谢。

如何在下一张图片中删除红色正方形区域?

image

class ViewController: UIViewController {

    let itemCount: Int = 10
    let tableView = UITableView()
    let cellWithButton = "cellWithButton"
    var isExpand: Bool = false
    var expandingStateArray: [Bool] = []

    let textArray: [String] = ["If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm", "If you read and listen to two", "If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day", "If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day", "If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day", "If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day", "If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day", "If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day", "If you read and listen to two articles every day, your reading and listening skills", "If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm If you read and listen to two articles every day, your reading and listening skills can immm"]

    override func viewDidLoad() {
        super.viewDidLoad()

        for _ in 0...itemCount-1 {
            let bool = false
            expandingStateArray.append(bool)
        }

        tableView.delegate = self
        tableView.dataSource = self
        tableView.allowsSelection = false
        tableView.separatorInset = .zero
        tableView.estimatedRowHeight = 44
        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.register(WithButtonTableViewCell.self, forCellReuseIdentifier: cellWithButton)

        self.view.addSubview(tableView)

        tableView.snp.makeConstraints { (make) in
            make.top.left.right.bottom.equalToSuperview()
        }
    }

    @objc func btnPressed(sender: UIButton) {

        let indexPath = IndexPath(row: sender.tag, section: 0)

        if self.isExpand == false {

            self.isExpand = true

            expandingStateArray[sender.tag] = true

        } else {
            self.isExpand = false

            expandingStateArray[sender.tag] = false
        }

        tableView.beginUpdates()
        tableView.reloadRows(at: [indexPath], with: .none)
        tableView.endUpdates()

    }


}

extension ViewController: UITableViewDelegate, UITableViewDataSource {

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

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

        let cell = tableView.dequeueReusableCell(withIdentifier: cellWithButton, for: indexPath) as! WithButtonTableViewCell

        cell.titleLabel.text = textArray[indexPath.row]
        cell.expandButton.addTarget(self, action: #selector(btnPressed), for: .touchUpInside)
        cell.expandButton.tag = indexPath.row

        if expandingStateArray[indexPath.row] {
            cell.titleLabel.numberOfLines = 0
            cell.expandButton.setTitle("Close.", for: .normal)
        }else{
            cell.titleLabel.numberOfLines = 2
            cell.expandButton.setTitle("Show More.", for: .normal)
        }

        return cell
    }

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {

        if let btnCell = cell as? WithButtonTableViewCell  {

            let labelIsTruncated: Bool = btnCell.titleLabel.isTruncated()

            btnCell.expandButton.isHidden = !labelIsTruncated
        }
    }
}

extension UILabel {

    func countLabelLines() -> Int {
        self.layoutIfNeeded()
        let myText = self.text! as NSString
        let attributes = [NSAttributedStringKey.font : self.font!]

        let labelSize = myText.boundingRect(with: CGSize(width: self.bounds.width, height: CGFloat.greatestFiniteMagnitude), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: attributes, context: nil)
        return Int(ceil(CGFloat(labelSize.height) / self.font.lineHeight))
    }

    func isTruncated() -> Bool {

        if (self.countLabelLines() > self.numberOfLines) {
            return true
        }
        return false
    }
}


import UIKit

class WithButtonTableViewCell: UITableViewCell {

    var cellIsExpand: Bool = false

    let titleLabel: UILabel = { () -> UILabel in
        let ui = UILabel()
        ui.textColor = UIColor.black
        ui.numberOfLines = 2
        return ui
    }()

    let expandButton: UIButton = { () -> UIButton in
        let ui = UIButton()
        ui.setTitleColor(UIColor.blue, for: .normal)
        return ui
    }()

    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        loadUI()
        loadLayout()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")

    }

    func loadUI() {

        self.addSubview(titleLabel)
        self.addSubview(expandButton)
    }

    func loadLayout() {

        titleLabel.snp.makeConstraints { (make) in
            make.top.left.equalTo(15)
            make.right.equalTo(-15)
        }

        expandButton.snp.makeConstraints { (make) in
            make.top.equalTo(titleLabel.snp.bottom).offset(10)
            make.left.equalTo(10)
            make.right.equalTo(-15)
            make.bottom.equalTo(-15)            
        }
    }
}

3 个答案:

答案 0 :(得分:0)

我认为ctreeinput是一项完美的工作,设置

UIStackView

将折叠内容,否则挂钩按钮的高度限制并将其设置为

self.expandButton.isHidden = true

要隐藏它时


btnCell.btnHCon?.constant = 0
btnCell.layoutIfNeeded()

答案 1 :(得分:0)

就像第一个评论所说: 使用自动调整大小的单元格时,应更新布局。因此,您应该设置一个高度约束,以使单元格的contentView知道它,并且当其子视图的约束更改时,该单元格将调整大小。 我下载了您的代码,并在下面对其进行了修改:

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

    let cell = tableView.dequeueReusableCell(withIdentifier: cellWithButton, for: indexPath) as! WithButtonTableViewCell

    cell.titleLabel.text = textArray[indexPath.row]
    cell.expandButton.addTarget(self, action: #selector(btnPressed), for: .touchUpInside)
    cell.expandButton.tag = indexPath.row

    if expandingStateArray[indexPath.row] {
        cell.titleLabel.numberOfLines = 0
        cell.expandButton.setTitle("Close.", for: .normal)
    }else{
        cell.titleLabel.numberOfLines = 2
        cell.expandButton.setTitle("Show More.", for: .normal)
    }

    let btnCell = cell
    let labelIsTruncated: Bool = btnCell.titleLabel.isTruncated()
    if !labelIsTruncated {
        btnCell.expandButton.snp.updateConstraints { (make) in
            make.height.equalTo(0)
        }
    }
    btnCell.expandButton.isHidden = !labelIsTruncated

    return cell
}

func loadLayout() {

    titleLabel.snp.makeConstraints { (make) in
        make.top.left.equalTo(15)
        make.right.equalTo(-15)
    }

    expandButton.snp.makeConstraints { (make) in
        make.top.equalTo(titleLabel.snp.bottom).offset(10)
        make.left.equalTo(10)
        make.right.equalTo(-15)
        make.bottom.equalTo(-15)
        make.height.equalTo(100)
    }
}

有效。最后,您不应该在cellDisplay方法中更改单元格子视图的布局。

已弃用: 我认为这是自动布局策略的问题,您可以在下面设置标签和按钮的布局:

    func loadLayout() {

    titleLabel.snp.makeConstraints { (make) in
        make.top.left.equalTo(15)
        make.right.equalTo(-15)
    }

    expandButton.snp.makeConstraints { (make) in
        make.top.equalTo(titleLabel.snp.bottom).offset(10)
        make.left.equalTo(10)
        make.right.equalTo(-15)
        make.bottom.equalTo(-15)
    }
}

仅当初始化单元格并且刷新表格视图并将按钮设置为隐藏时,才会调用该约束。 我建议您手动计算此单元格的高度。 当您使用自动像元高度时,必须有一些高级方法来保持自动调整大小。我也在学习这一部分,当我找到理想的方法时,我会告诉你。 希望对您有帮助。

答案 2 :(得分:0)

让高度限制显示更多按钮,并在不想显示时将其设置为0。