我正在创建一个应用程序,其中会在UILabel
中提出问题,并在UITableView
中显示多个选择答案,每一行显示一个选择。 由于问题和答案各不相同,因此我需要这个UITableView
的高度是动态的。
我希望找到一个sizeToFit
的解决方法,使表格的框架设置为其所有内容的高度。
有人能指导我如何实现吗?
我正在创建一个应用程序,其中会在UILabel
中提出问题,并在UITableView
中显示多个选择答案,每一行显示一个选择。 由于问题和答案各不相同,因此我需要这个UITableView
的高度是动态的。
我希望找到一个sizeToFit
的解决方法,使表格的框架设置为其所有内容的高度。
有人能指导我如何实现吗?
不需要使用KVO、DispatchQueue或手动设置约束的Swift 5和4.2解决方案。
这个解决方案基于Gulz的回答。
创建一个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 + adjustedContentInset.top)
}
}
将UITableView
添加到您的布局中,并在所有边上设置约束。将底部约束关系设置为>=(大于等于)。
将其自定义类设置为ContentSizedTableView
。
您可能会看到一些错误,因为Storyboard没有考虑我们子类的intrinsicContentSize
。通过打开大小检查器并将intrinsicContentSize覆盖为占位符值来修复此问题。这是设计时的覆盖。在运行时,它将使用我们ContentSizedTableView
类中的覆盖。
更新:更改了适用于Swift 4.2的代码。如果您使用的是早期版本,请使用UIViewNoIntrinsicMetric
代替UIView.noIntrinsicMetric
tableView
的类更改为IntrinsicTableView
。我不需要将我的表视图嵌入到另一个UIView
中。 - dvp.petrovtableView.sizeToFit()
- Soufiane ROCHDIsizeToFit()
。 - heyfrankintrinsicContentSize
:override var intrinsicContentSize: CGSize {
layoutIfNeeded()
if contentSize.height > 0 {
return CGSize(width: UIView.noIntrinsicMetric, height: contentSize.height)
} else {
return super.intrinsicContentSize
}
}
- cuddergambino实际上,我自己找到了答案。
我只是为 tableView.frame
创建一个新的 CGRect
,其高度为 table.contentSize.height
。
这将设置 UITableView
的高度为其内容的高度。
由于代码修改了UI,请不要忘记在主线程中运行它:
dispatch_async(dispatch_get_main_queue(), ^{
//This code will run in the main thread:
CGRect frame = self.tableView.frame;
frame.size.height = self.tableView.contentSize.height;
self.tableView.frame = frame;
});
Swift 解决方案
按照以下步骤进行操作:
在 storyboard 中为表格设置高度约束。
从 storyboard 拖拽高度约束并在视图控制器文件中创建 @IBOutlet
。
@IBOutlet var tableHeight: NSLayoutConstraint!
接下来你可以使用以下代码动态地改变表格的高度:
override func viewWillLayoutSubviews() {
super.updateViewConstraints()
self.tableHeight?.constant = self.table.contentSize.height
}
如果最后一行被截断,请尝试在willDisplay cell
函数中调用viewWillLayoutSubviews()
:
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
self.viewWillLayoutSubviews()
}
我在 iOS 7 上尝试过这个方法,它对我有效。
- (void)viewDidLoad
{
[super viewDidLoad];
[self.tableView sizeToFit];
}
为表视图的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;
}
希望这可以帮助你。
我在滚动视图内部放置了一个表格视图并需要计算表格视图的高度并相应地调整大小。以下是我采取的步骤:
0)向你的滚动视图添加一个UIView(可能不需要这一步,但我这样做是为了避免任何可能的冲突)-这将是你的表格视图的容器视图。如果你采取了这个步骤,则将该视图的边框设置为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)将高度约束设置为您的表视图
4)将表格的IBoutlet拖到您的ViewController上
5)将表格高度约束的IBoutlet拖到您的ViewController上
6)将此方法添加到您的ViewController中:
override func viewWillLayoutSubviews() {
super.updateViewConstraints()
self.yourTableViewsHeightConstraint?.constant = self.yourTableView.intrinsicContentSize.height
}
希望这可以帮到你。Swift 5 解决方案
按照以下四个步骤进行操作:
从故事板中设置表格视图的高度约束。
从故事板中拖动高度约束,并在视图控制器文件中创建一个 @IBOutlet
引用它。
@IBOutlet var tableViewHeightConstraint: NSLayoutConstraint!
在 override func viewDidLoad()
中为 contentSize
属性添加观察者。
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
}
接着,您可以使用以下代码动态更改表的高度:
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
if(keyPath == "contentSize"){
if let newvalue = change?[.newKey]
{
DispatchQueue.main.async {
let newsize = newvalue as! CGSize
self.tableViewHeightConstraint.constant = newsize.height
}
}
}
}
如果您不想自己跟踪表格视图的内容大小更改,您可能会发现这个子类很有用。
protocol ContentFittingTableViewDelegate: UITableViewDelegate {
func tableViewDidUpdateContentSize(_ tableView: UITableView)
}
class ContentFittingTableView: UITableView {
override var contentSize: CGSize {
didSet {
if !constraints.isEmpty {
invalidateIntrinsicContentSize()
} else {
sizeToFit()
}
if contentSize != oldValue {
if let delegate = delegate as? ContentFittingTableViewDelegate {
delegate.tableViewDidUpdateContentSize(self)
}
}
}
}
override var intrinsicContentSize: CGSize {
return contentSize
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
return contentSize
}
}
override public var intrinsicContentSize: CGSize { //... return someCGSize }
。 - xaphod来源: https://forums.developer.apple.com/thread/81895tableView.estimatedRowHeight = 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()
}
}
-sizeToFit
方法? - Slipp D. Thompson