如果禁用滚动,您是否可以根据显示的行数更新UITableView的内在内容大小?

时间:2016-09-21 20:39:03

标签: swift uitableview ios8 autolayout

我们的UI的一部分是一个小标签列表,旁边有颜色样本。即使实际数据是动态的,我接管的设计在布局中有六个硬编码,这意味着如果我们只需要显示三个,我们必须明确隐藏三个,这也会抛弃页面的平衡。更糟糕的是,这些“项目”中的每一个实际上都是由几个子视图组成的,因此一个包含六个硬编码项目的屏幕有十八个IBOutlets。

我要做的是改为使用UITableView来代表屏幕的这一小部分,因为它不会滚动,我想知道你是否可以使用AutoLayout来配置内在内容UITableView的高度取决于行数。

目前我有一个UITableView垂直约束到中心的测试页面,但没有高度限制因为我希望表格的内在内容大小反映可见行。我也禁止在桌面上滚动。当我重新加载表时,我调用updateConstraints。但是表格仍然没有调整大小。

注意:我们不能使用UIStackView(这可能是完美的),因为我们必须针对iOS8,直到iOS9才会引入,因此这个解决方案。

有没有人能够做出类似我们需要的事情?

4 个答案:

答案 0 :(得分:3)

好吧,与UITextView不同,UITableView似乎不会根据可见行返回内在大小。但是通过子类实现并不是那么重要,特别是如果只有一个部分,没有页眉或页脚,并且行的高度是固定的。

class AutoSizingUiTableView : UITableView
{
    override func intrinsicContentSize() -> CGSize
    {
        let requiredHeight = rowCount * rowHeight
        return CGSize(width: -1, height: requiredHeight)
    }
}

我会让读者知道如何获得自己的rowCount。如果您有可变高度,多个部分等,则相同。您只需要更多逻辑。

通过这样做,它适用于AutoLayout。我只是希望它能自动处理。

答案 1 :(得分:1)

在这里查看我的答案:

https://stackoverflow.com/a/48623673/4846592

答案 2 :(得分:0)

这可以完成,请参阅下面的一个非常简单的(粗略 - 旋转无法正常工作!)示例,它允许您通过在文本字段中输入数字并使用以下内容重置来更新表格视图的大小一个按钮。

import UIKit

class ViewController: UIViewController {

    var tableViewController : FlexibleTableViewController!
    var textView : UITextView!
    var button : UIButton!
    var count : Int! {
        didSet {
            self.refreshDataSource()
        }
    }
    var dataSource : [Int]!
    let rowHeight : CGFloat = 50

    override func viewDidLoad() {
        super.viewDidLoad()

        // Configure

        self.tableViewController = FlexibleTableViewController(style: UITableViewStyle.plain)

        self.count = 10
        self.tableViewController.tableView.backgroundColor = UIColor.red

        self.textView = UITextView()
        self.textView.textAlignment = NSTextAlignment.center
        self.textView.textColor = UIColor.white
        self.textView.backgroundColor = UIColor.blue

        self.button = UIButton()
        self.button.setTitle("Reset", for: UIControlState.normal)
        self.button.setTitleColor(UIColor.white, for: UIControlState.normal)
        self.button.backgroundColor = UIColor.red
        self.button.addTarget(self, action: #selector(self.updateTable), for: UIControlEvents.touchUpInside)

        self.layoutFrames()

        // Assemble
        self.view.addSubview(self.tableViewController.tableView)
        self.view.addSubview(self.textView)
        self.view.addSubview(self.button)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    func refreshDataSource() -> Void {
        if let _ = self.dataSource {
            if !self.dataSource.isEmpty {
                self.dataSource.removeAll()
            }
        }
        else
        {
            self.dataSource = [Int]()
        }

        for count in 0..<self.count {
            self.dataSource.append(count)
        }

        self.tableViewController.dataSource = self.dataSource
        self.tableViewController.tableView.reloadData()
        if let _ = self.view {
            self.layoutFrames()
            self.view.setNeedsDisplay()
        }
    }

    func updateTable() -> Void {
        guard let _ = self.textView.text else { return }
        guard let validNumber = Int(self.textView.text!) else { return }

        self.count = validNumber
    }

    func layoutFrames() -> Void {

        if self.tableViewController.tableView != nil {
            self.tableViewController.tableView.frame = CGRect(origin: CGPoint(x: self.view.frame.width / 2 - 100, y: 100), size: CGSize(width: 200, height: CGFloat(self.dataSource.count) * self.rowHeight))
            NSLog("\(self.tableViewController.tableView.frame)")
        }

        if self.textView != nil {
            self.textView.frame = CGRect(origin: CGPoint(x: 50, y: 100), size: CGSize(width: 100, height: 100))
        }

        if self.button != nil {
            self.button.frame = CGRect(origin: CGPoint(x: 50, y: 150), size: CGSize(width: 100, height: 100))
        }
    }
}

class FlexibleTableViewController : UITableViewController {

    var dataSource : [Int]!

    override init(style: UITableViewStyle) {
        super.init(style: style)
    }

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

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

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.dataSource.count
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")

        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") ?? UITableViewCell()

        cell.frame = CGRect(origin: CGPoint(x: 10, y: 5), size: CGSize(width: 180, height : 40))
        cell.backgroundColor = UIColor.green

        return cell
    }

}

是否是一个好主意,正如已经指出的那样,是另一个问题!希望有所帮助!

答案 3 :(得分:0)

//定义这只小狗:

class AutoTableView: UITableView {   

    override func layoutSubviews() {
        super.layoutSubviews()
        self.invalidateIntrinsicContentSize()
    }

    override var intrinsicContentSize: CGSize {
        get {
            var height:CGFloat = 0;
            for s in 0..<self.numberOfSections {
                let nRowsSection = self.numberOfRows(inSection: s)
                for r in 0..<nRowsSection {
                    height += self.rectForRow(at: IndexPath(row: r, section: s)).size.height;
                }
            }
            return CGSize(width: -1, height: height )
        }
        set {
        }
    }
}

,并使其成为IB课程。 obs:这是如果您的班级只有牢房和狗屎。如果它有页眉,页脚或其他样式,则为dunno。它不会工作。就我的目的而言

和平