【问题标题】:Self sizing tableview inside self sizing tableview cell自定尺寸表视图单元内的自定尺寸表视图
【发布时间】:2019-12-04 14:34:02
【问题描述】:

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

*TableViewCell
**TableView
***TableViewCell

并且它们都应该是可调整大小的。有人遇到过这种问题吗?在过去,我使用了许多解决方法,例如systemLayoutSizeFittingheightForRowAt 中的高度预计算,但它总是打破一些约束,因为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
    }
}

【问题讨论】:

  • 我会尝试为单元格设置自动维度,为 tableView 设置动态高度(高度优先级 = 750,isScrollEnabled = false),或者尝试将表格高度设置为其 contentSize
  • @AlexandrKolesnik 我提供了更多信息,请查看:)。然后,contentSize 的单元格中的automaticDimension 等于estimatedRowHeight,它将设置tableView height = estimatedRowHeight * numberOfRows
  • @PrashantTukadiya 抱歉,但您的解决方案对我来说看起来很重要。我需要更稳定的东西。
  • 很有趣的问题,找我在GitHub上创建的项目github.com/barbados88/cell-table-cell,稍后我会尝试在没有解决方法的情况下进行。对不起,脏代码

标签: ios swift uitableview uitableviewautomaticdimension


【解决方案1】:

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

您应该为内部 tableViews 使用“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
    }
}

【讨论】:

  • 我在您的解决方案中看不到内部 tableView :)。然后,我在问题详细信息方面有相同的解决方法。
  • 那么,contentSize 的单元格中有automaticDimension 等于estimatedRowHeight,它将设置tableView height = estimatedRowHeight * numberOfRows
【解决方案2】:
  • 使用 xib 文件来简化层次结构。
  • 在情节提要上获取 tableView,并为 tableViewCell(例如 CustomTableViewCell)创建一个 nib 文件。在其中创建一个 tableView 并再次创建一个 tableViewCell xib 文件。现在,无需在您的 xib 文件中设置标签,(如果您只想要单元格中的标签而不需要其他任何内容,如果没有,还有另一种添加约束的方法)
  • 假设您有一个文本数组,有些字符串很长,有些字符串很短。
  • 在 CustomTableViewCell 中注册 nib 文件并将其扩展为使用 Delegate 和 DataSource。
  • 在 ViewController 中注册这个 CustomTableViewCell。
  • 在 CustomTableViewCell 中声明单元格时,只需这样做=
  • cell.textLabel?.text = 内容
  • cell.textLabel?.numberOfLines = 0
  • 使用heightForRowAt设置outer tableViewCell的高度,让inner tableView向内滚动。

【讨论】:

    【解决方案3】:

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

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

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

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

    【讨论】:

    • 非常有趣的想法,我没有亲自接触,谢谢!
    • @Erumaru 但同样,正确的解决方案是使用多部分表格视图。让您的单元格成为节标题,内部单元格成为表格视图的行
    • 这是我的解决方案 :)
    • 很高兴知道:)
    • 请稍微修改一下您的答案,以便包含您对多部分表格视图的建议。我相信它会帮助某人:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-03-24
    • 1970-01-01
    • 2016-07-07
    • 1970-01-01
    • 2021-10-22
    • 1970-01-01
    相关资源
    最近更新 更多