如何在Swift中使用两个TableView设计动态布局

时间:2019-03-08 13:27:47

标签: ios swift uitableview autolayout ios-autolayout

嗨,程序员。

我花了很多时间试图在Swift中设计这种布局,但收效甚微。

Drawing of the layout

这个想法是有两个TableViews:

  • 最上面的一个,具有零个或多个(未定义)单元格,这些单元格不可滚动,并且其高度随着单元格的数量而增加。
  • 底部的一个具有零个或多个(不确定的)单元格,该单元格是可滚动的,因此其高度适应于后一个表格视图剩下的空间。

我已经尝试通过编程方式来处理约束,方法是将两个表的top约束都设置到屏幕顶部,然后根据top TableView的大小修改该约束。似乎不起作用。

我还尝试根据要绘制的单元格的数量,以编程方式修改表格的高度。也没用。

老实说,我现在正处于一个死点,我正在寻找帮助或一些新想法来使其工作。任何帮助将不胜感激。预先感谢!

1 个答案:

答案 0 :(得分:0)

您需要确定一些其他逻辑-例如,当顶表视图中的行太多时该怎么办,但这是一种方法:

使用此自定义表格视图类(来自https://stackoverflow.com/a/48623673/6257435):

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

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

每当内容大小更改时,它将“自动调整大小”您的表视图。要使用它,请添加一个表视图并将其类设置为ContentSizedTableView

  • 根据需要约束顶部,前导和尾随。
  • 将底部限制为底部表格视图的顶部。
  • 赋予高度限制-并不重要,但是使用200可以处理布局。但是...编辑该高度限制并选中占位符-在构建时删除复选框。
  • 根据需要将底部表格视图限制为开头,结尾和底部。

现在,当您将行添加到top table view时,它将自动垂直扩展,而bottom table view将自动垂直收缩(直到消失)。由于top table view底部仍受约束于{{1}的 top ,因此bottom table view将停止增长并可以滚动(而不是扩展到视图底部)。

这是一个非常简单的示例:

top table view

顶部有8行,底部有12行,我们得到:

enter image description here

,顶部有11行:

enter image description here

最后是顶部的17行(滚动显示,可以看到):

enter image description here

以下是该示例的情节提要源:

import UIKit

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

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

class SimpleTopCell: UITableViewCell {

    @IBOutlet var theLabel: UILabel!

}

class SimpleBottomCell: UITableViewCell {

    @IBOutlet var theLabel: UILabel!

}


class AutoSizeTableViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {

    @IBOutlet var topTableView: ContentSizedTableView!

    @IBOutlet var bottomTableView: UITableView!

    var numRowsTop = 8
    var numRowsBottom = 12

    override func viewDidLoad() {
        super.viewDidLoad()

        topTableView.dataSource = self
        bottomTableView.dataSource = self

        topTableView.delegate = self
        bottomTableView.delegate = self

    }

    @IBAction func addRowTapped(_ sender: Any) {
        numRowsTop += 1
        topTableView.reloadData()
    }

    @IBAction func delRowTapped(_ sender: Any) {
        numRowsTop -= 1
        // make sure it's at least 1
        numRowsTop = max(numRowsTop, 1)
        topTableView.reloadData()
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        if tableView == topTableView {
            return numRowsTop
        }
        return numRowsBottom
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if tableView == topTableView {
            let cell = tableView.dequeueReusableCell(withIdentifier: "SimpleTopCell", for: indexPath) as! SimpleTopCell
            cell.theLabel.text = "Top: \(indexPath)"
            return cell
        }
        let cell = tableView.dequeueReusableCell(withIdentifier: "SimpleBottomCell", for: indexPath) as! SimpleBottomCell
        cell.theLabel.text = "Bottom: \(indexPath)"
        return cell
    }

}