繁体   English   中英

自调整tableview单元内的自调整tableview

[英]Self sizing tableview inside self sizing tableview cell

假设我有这样的层次结构:

*TableViewCell
**TableView
***TableViewCell

所有这些都应调整大小。 有人遇到过这种问题吗? 过去,我使用过许多变通方法,例如systemLayoutSizeFittingheightForRowAt的height的预先计算,但它总是会打破一些约束,因为TableViewCell高度约束等于估算的行高,并且会出现某种魔术行为。 有什么办法可以使它成为现实?

当前解决方法:

class SportCenterReviewsTableCell: UITableViewCell, MVVMView {
    var tableView: SelfSizedTableView = {
        let view = SelfSizedTableView(frame: .zero)
        view.clipsToBounds = true
        view.tableFooterView = UIView()
        view.separatorStyle = .none
        view.isScrollEnabled = false
        view.showsVerticalScrollIndicator = false
        view.estimatedRowHeight = 0
        if #available(iOS 11.0, *) {
            view.contentInsetAdjustmentBehavior = .never
        } else {
            // Fallback on earlier versions
        }

        return view
    }()

    private func markup() {
        contentView.addSubview(tableView)
        tableView.delegate = self
        tableView.dataSource = self
        tableView.register(ReviewsTableViewCell.self, forCellReuseIdentifier: "Cell")
        tableView.snp.makeConstraints() { make in
            make.top.equalTo(seeAllButton.snp.bottom).offset(12)
            make.left.equalTo(contentView.snp.left)
            make.right.equalTo(contentView.snp.right)
            make.bottom.lessThanOrEqualTo(contentView.snp.bottom)
        }
    }


    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! ReviewsTableViewCell

        cell.viewModel = viewModel.cellViewModels[indexPath.row]

        return cell
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! ReviewsTableViewCell

        cell.viewModel = viewModel.cellViewModels[indexPath.row]
        cell.setNeedsLayout()
        cell.layoutIfNeeded()
        let size = cell.contentView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize, withHorizontalFittingPriority: .defaultHigh, verticalFittingPriority: .defaultLow)

        return size.height
    }
}

自定义tableView类:

class SelfSizedTableView: UITableView {
    override func reloadData() {
        super.reloadData()
        self.invalidateIntrinsicContentSize()
        self.layoutIfNeeded()
    }

    override var intrinsicContentSize: CGSize {
        self.setNeedsLayout()
        self.layoutIfNeeded()
        return contentSize
    }
}

这实际上不是对问题的答案,而只是一种解释。
(在这里写是因为注释的字符数限制)。

问题是您试图在另一个垂直滚动视图内插入一个垂直滚动视图。 如果不禁用嵌套表视图的滚动功能,则滚动时会出现故障,因为系统将不知道向谁传递滚动事件(嵌套表视图或父表视图)。 因此,在我们的案例中,您必须为嵌套表视图禁用“ scrollable”属性,因此必须将嵌套表视图的高度设置为等于其内容大小。 但是这样一来,您将失去tableview的优势(即单元重用优势),并且与使用实际的UIScrollView相同。 但是,另一方面,由于必须将高度设置为等于其内容大小,因此根本没有理由使用UIScrollView,您可以将嵌套的单元格添加到UIStackView中,并且tableview将具有此层次结构:

*TableView
**TableViewCell
***StackView
****Items
****Items
****Items
****Items

但同样,正确的解决方案是使用多部分表格视图。 让您的单元格成为表格视图的节标题,让内部单元格成为表格视图的行。

这是一个如何在表格视图单元格内创建具有自动高度的表格视图的示例。

您应该对内部tableView使用“ ContentSizedTableView”类。

class ViewController: UIViewController {

    @IBOutlet weak var outerTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        outerTableView.rowHeight = UITableView.automaticDimension
        outerTableView.estimatedRowHeight = UITableView.automaticDimension
        outerTableView.delegate = self
        outerTableView.dataSource = self
    }

}

final class ContentSizedTableView: UITableView {
    override var contentSize:CGSize {
        didSet {
            invalidateIntrinsicContentSize()
        }
    }

    override var intrinsicContentSize: CGSize {
        layoutIfNeeded()
        sizeToFit()
        return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
    }
}

extension ViewController: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

        return 10
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? TableTableViewCell

        return cell!
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }
}
  • 使用xib文件简化层次结构。
  • 在情节提要上获取tableView,并为tableViewCell(例如CustomTableViewCell)创建一个nib文件。 在其中创建一个tableView,然后再次创建一个tableViewCell xib文件。 现在,无需在xib文件中设置标签(如果您只希望在单元格中放置标签,而无需其他标签,则不需要添加约束的另一种方法)
  • 假设您有一组文本,有些字符串很长,有些则很短。
  • 在CustomTableViewCell中注册笔尖文件,并将其扩展为使用Delegate和DataSource。
  • 在ViewController中注册此CustomTableViewCell。
  • 在CustomTableViewCell中声明单元格时,只需执行=
  • cell.textLabel?.text =内容
  • cell.textLabel?.numberOfLines = 0
  • 使用heightForRowAt设置外部tableViewCell的高度,并让内部tableView向内滚动。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM