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

Posted

技术标签:

【中文标题】如何更改 tableview willDisplay 函数中的布局和属性设置?【英文标题】:How to change layout and property setting in tableview willDisplay function? 【发布时间】:2018-12-27 03:05:36 【问题描述】:

我有一个问题。 我有一个 UITableView 和一个自定义 UITableViewCell。 首先,我将检查自定义 UITableViewCell 中的 UILabel 是否被截断。 如果 UILabel 被截断,我将显示 UIButton“显示更多”,并将 UILabel numberOfLines 设置为 2。 当我单击 UIButton“显示更多”时,我将 UILabel numberOfLines 设置为 0,并且 UIButton 标题更改为“关闭”。 UITableViewCell 的高度是根据 UILabel 内容展开的。 如果 UILabel 没有被截断,我不会显示 UIButton 并将 UILabel numberOfLines 设置为 0。 UITableViewCell 的高度也是根据 UILabel 内容展开的。 如何实现这种情况? 谢谢。

如何去除下图中的红色方块?

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)            
        
    

【问题讨论】:

【参考方案1】:

我认为这是一个完美的工作 UIStackView ,作为设置

self.expandButton.isHidden = true

将折叠内容,否则钩住按钮的高度约束并将其设置为

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

当你想隐藏它时


var btnHCon: Constraint? = nil

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)  
    self.btnHCon = make.height.equalTo(40).constraint


【讨论】:

我找不到 btnCell.btnHCon?.constant = 0 ,我用的是 xcode9.4.1, snapKit 4.0.0 并得到一个错误“常量”由于“私人”保护级别而无法访问【参考方案2】:

给显示更多按钮设置高度限制,当你不想显示时将其设置为0。

【讨论】:

有什么例子吗?【参考方案3】:

就像第一条评论说的: 当您使用自调整单元格时,您应该更新布局。因此,您应该设置一个高度约束,让单元格的 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)
    

它只会在单元格初始化时被调用,当你刷新tableview并设置按钮隐藏时,约束不会改变。 我建议您手动计算此单元格的高度。 当您使用自动单元格高度时,必须有一些高级方法来保持自调整大小。这部分我也在学习,等找到完美的方法再告诉你。 我希望这对你有帮助。

【讨论】:

我记得我尝试让 labelIsTruncated 在“cellForRow”中,并且 labelIsTruncated 始终为真。所以,我改为让 labelIsTruncated 在“willDisplay”中

以上是关于如何更改 tableview willDisplay 函数中的布局和属性设置?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据 tableview 选择更改按钮的功能?

如何在tableview标题中更改uiview的高度

如何在 UIViewController 中更改 TableView 的属性

如何在 swift 中更改 tableView 部分中的文本颜色

重新排序 TableView 时如何更改 CoreData 的索引?

单击tableview单元iphone时如何更改图像