我正在创建一个应用程序,它将在UILabel中有一个问题,并在UITableView中显示多项选择的答案,每行显示多项选择。问题和答案会有所不同,所以我需要这个UITableView的高度是动态的。

我想为桌子周围找一个合适的尺寸。其中,表的框架被设置为所有内容的高度。

有人能给我一些建议吗?


当前回答

我用了一点不同的方式,实际上我的TableView在scrollview内部,所以我必须给高度约束为0。

然后在运行时,我做了以下更改,

       func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
            self.viewWillLayoutSubviews()
       }
    
       override func viewWillLayoutSubviews() {
            super.updateViewConstraints()
             DispatchQueue.main.async {
               self.tableViewHeightConstraint?.constant = self.myTableView.contentSize.height
               self.view.layoutIfNeeded()
          }
       }

其他回答

我在滚动视图中有一个表格视图,必须计算tableView的高度并相应地调整它的大小。这些是我已经采取的步骤:

0)添加一个UIView到你的scrollView(可能会工作没有这一步,但我这样做是为了避免任何可能的冲突)-这将是一个容器视图为您的表视图。如果你采取了这一步,然后将视图的边界设置为tableview的边界。

1)创建UITableView的子类:

class IntrinsicTableView: UITableView {

    override var contentSize:CGSize {
        didSet {
            self.invalidateIntrinsicContentSize()
        }
    }

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

}

2)在Storyboard中设置一个表视图的类为IntrinsicTableView:截图:http://joxi.ru/a2XEENpsyBWq0A

3)设置heightConstraint到你的表视图

4)拖动你的表的IBoutlet到你的ViewController

5)拖动你的表高度约束的IBoutlet到你的ViewController

6)将这个方法添加到你的ViewController中:

override func viewWillLayoutSubviews() {
        super.updateViewConstraints()
        self.yourTableViewsHeightConstraint?.constant = self.yourTableView.intrinsicContentSize.height
    }

希望这能有所帮助

我使用的是UIView扩展,方法接近上面的@ChrisB方法

 extension UIView {
func updateHeight(_ height:NSLayoutConstraint)
{
    
    let newSize = CGSize(width: self.frame.size.width, height: CGFloat(MAXFLOAT))
    let fitSize : CGSize = self.sizeThatFits(newSize)
    
    height.constant = fitSize.height
    
   
}
}

实现::

@IBOutlet weak var myTableView: UITableView!
@IBOutlet weak var myTableVieweHeight: NSLayoutConstraint!
//(call it whenever tableView is updated inside/outside delegate methods)
myTableView.updateHeight(myTableVieweHeigh)

好处:可以用在任何其他的uiview,例如:你自己的动态标签

Swift 5和4.2解决方案没有KVO, DispatchQueue,也没有自己设置约束。

这个解决方案基于古尔兹的回答。

1)创建UITableView的子类:

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)
    }
}

2)添加一个UITableView到你的布局和设置约束的所有方面。将它的类设置为contentsizetableview。

3)你应该会看到一些错误,因为Storyboard没有考虑子类的intrinsicContentSize。通过打开大小检查器并将intrinsicContentSize重写为一个占位符值来修复此问题。这是设计时的重写。在运行时,它将在contentsizetableview类中使用重写


更新:更改了Swift 4.2的代码。如果你使用的是以前的版本,使用UIViewNoIntrinsicMetric而不是UIView.noIntrinsicMetric

Mimo和Anooj VM的答案都很棒,但如果你有一个很大的列表,有可能帧的高度会截断你的一些单元格,这是个小问题。

所以。我稍微修改了一下答案:

dispatch_async(dispatch_get_main_queue()) {
    //This code will run in the main thread:
    CGFloat newHeight=self.tableView.contentSize.height;
    CGFloat screenHeightPermissible=(self.view.bounds.size.height-self.tableView.frame.origin.y);
    if (newHeight>screenHeightPermissible)
    {
        //so that table view remains scrollable when 'newHeight'  exceeds the screen bounds
        newHeight=screenHeightPermissible;
    }

    CGRect frame = self.tableView.frame;
    frame.size.height = newHeight;
    self.tableView.frame = frame;
}

在表视图上为contentSize属性添加一个观察者,并相应地调整帧大小

[your_tableview addObserver:self forKeyPath:@"contentSize" options:0 context:NULL];

然后在回调中:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
         CGRect frame = your_tableview.frame;
         frame.size = your_tableview.contentSize;
         your_tableview.frame = frame;
    }

希望这对你有所帮助。