簡體   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