以编程方式创建扩展的UItableViewCell

时间:2017-12-24 19:43:27

标签: ios uitableview

我有一个tableviewcell,我想要扩展和折叠。我发现的所有示例都是Storyboard基础,我正在尝试以编程方式执行此操作。我最初的想法是创建一个子视图并将其约束到内容视图,但是当我用heightForRowAt调整单元格的高度时,它也增加了内容视图的大小(这是有意义的)。关于我应该怎么做的任何想法?

对于视觉参考,这里是我想要发生的事情enter image description here

3 个答案:

答案 0 :(得分:4)

在底部视图UIStackView设置为true的情况下使用纵向isHidden,然后点击(或扩展的触发器)只需更改isHidden = false。考虑UIStackView处理isHidden的方式,我想这是最简单的。另一种方法是设置自动布局约束,并通过将NSLayoutConstraint的常量设置为0来更改底部视图的高度锚点。

无论如何,无论你选择哪个appraoch,你都必须告诉tableView刷新它的显示(来自viewcontroller):

func refreshTableAfterCellExpansion() {
    self.tableView.beginUpdates()
    self.tableView.setNeedsDisplay()
    self.tableView.endUpdates()
}

例如,检查SO question及其answer

使用游乐场的示例(带有UIStackView的游戏,另一个使用相同的原则):

import UIKit
import PlaygroundSupport

class ExpandableCellViewController: UITableViewController, ExpandableCellDelegate {

    override func loadView() {
        super.loadView()

        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 44
        tableView.register(ExpandableCell.self, forCellReuseIdentifier: "expandableCell")
    }

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "expandableCell", for: indexPath) as! ExpandableCell
        cell.delegate = self
        return cell
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if let cell = tableView.cellForRow(at: indexPath) as? ExpandableCell {
            cell.isExpanded = true
        }
    }

    override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
        if let cell = tableView.cellForRow(at: indexPath) as? ExpandableCell {
            cell.isExpanded = false
        }
    }

    func expandableCellLayoutChanged(_ expandableCell: ExpandableCell) {
        refreshTableAfterCellExpansion()
    }

    func refreshTableAfterCellExpansion() {
        self.tableView.beginUpdates()
        self.tableView.setNeedsDisplay()
        self.tableView.endUpdates()
    }
}

protocol ExpandableCellDelegate: class {
    func expandableCellLayoutChanged(_ expandableCell: ExpandableCell)
}

class ExpandableCell: UITableViewCell {
    weak var delegate: ExpandableCellDelegate?

    fileprivate let stack = UIStackView()
    fileprivate let topView = UIView()
    fileprivate let bottomView = UIView()

    var isExpanded: Bool = false {
        didSet {
            bottomView.isHidden = !isExpanded
            delegate?.expandableCellLayoutChanged(self)
        }
    }

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

        selectionStyle = .none

        contentView.addSubview(stack)
        stack.addArrangedSubview(topView)
        stack.addArrangedSubview(bottomView)

        stack.translatesAutoresizingMaskIntoConstraints = false
        topView.translatesAutoresizingMaskIntoConstraints = false
        bottomView.translatesAutoresizingMaskIntoConstraints = false

        NSLayoutConstraint.activate([
            stack.topAnchor.constraint(equalTo: contentView.topAnchor),
            stack.leftAnchor.constraint(equalTo: contentView.leftAnchor),
            stack.rightAnchor.constraint(equalTo: contentView.rightAnchor),
            stack.bottomAnchor.constraint(equalTo: contentView.bottomAnchor),

            topView.heightAnchor.constraint(equalToConstant: 50),

            bottomView.heightAnchor.constraint(equalToConstant: 30),
            ])

        stack.axis = .vertical
        stack.distribution = .fill
        stack.alignment = .fill
        stack.spacing = 0

        topView.backgroundColor = .red
        bottomView.backgroundColor = .blue
        bottomView.isHidden = true
    }

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

// Present the view controller in the Live View window
PlaygroundPage.current.liveView = ExpandableCellViewController()

答案 1 :(得分:0)

我只想定义2个单元格类型,并选择适合tableView的那个(_ tableView:UITableView,cellForRowAt indexPath:IndexPath)

答案 2 :(得分:0)

您可以使用标志来指示是否展开了特定的部分或行,并在UITableView上使用此方法:

    reloadRows()
    reloadSections()

并根据标志更改heightForRow方法返回所需高度。 如果您希望一次扩展多行,则可以对数据源中的每个项使用ViewModel,并在调用didSelectItemAt或didDeselectItemAt方法时更新其中的标志,然后使用所需的动画重新加载行或节。 / p>