调整UITableView的大小以适应内容

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

我想find一个sizeToFit工作周围的表。 桌子的框架设置为所有内容的高度。

任何人都可以build议我怎么能做到这一点?

其实我自己find了答案

我只是用CGRectheighttableView.frame创build一个新的table.contentSize.height

这将UITableViewheight设置为其内容的height 。 由于代码修改了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; }); 

我已经在iOS 7中尝试了这一点,它为我工作

 - (void)viewDidLoad { [super viewDidLoad]; [self.tableView sizeToFit]; } 

Swift 3解决scheme遵循这些步骤

1-设置故事板中表格的高度限制。

2-从故事板拖动高度约束,并在viewController文件中为其创build@IBOutlet。

  @IBOutlet weak var tableHeight: NSLayoutConstraint! 

3-然后你可以使用下面的代码改变表的高度:

 override func viewWillLayoutSubviews() { super.updateViewConstraints() self.tableHeight?.constant = self.table.contentSize.height } 

在表视图中为contentSize属性添加观察者,并相应地调整框架大小

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

然后在callback中:

 - (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; } 

希望这会帮助你。

如果你不想跟踪表视图的内容大小变化,你可能会发现这个子类很有用。

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

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

如果使用AutoLayout,还有更好的方法:更改决定高度的约束。 只要计算你的表格内容的高度,然后find约束并改变它。 下面是一个例子(假设决定表格高度的约束实际上是一个高度约束,关系“Equal”):

 override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) for constraint in tableView.constraints { if constraint.firstItem as? UITableView == tableView { if constraint.firstAttribute == .height { constraint.constant = tableView.contentSize.height } } } } 

Swift 3,iOS 10.3

解决scheme1:只需将self.tableview.sizeToFit()放在cellForRowAt indexPath函数中。 确保将tableview的高度设置得更高,然后你需要。 这是一个很好的解决scheme,如果你没有视图下面的tableview。 但是,如果你有,底部tableview约束不会更新(我没有尝试解决它,因为我想出了解决scheme2)

例:

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath) as? TestCell { cell.configureCell(data: testArray[indexPath.row]) self.postsTableView.sizeToFit() return cell } return UITableViewCell() } 

解决scheme2:在故事板中设置tableview高度约束,并将其拖到ViewController。 如果你知道你的单元格的平均高度,并且你知道你的数组包含了多less元素,你可以这样做:

 tableViewHeightConstraint.constant = CGFloat(testArray.count) * 90.0 // Let's say 90 is the average cell height 

*编辑:

在我尝试了所有的解决scheme之后,他们每个人都在解决某些问题,但不是完全解决这个问题的答案。

对于这个在swift 3中的解决scheme :在viewDidAppear调用这个方法

 func UITableView_Auto_Height(_ t : UITableView) { var frame: CGRect = t.frame; frame.size.height = t.contentSize.height; t.frame = frame; } 

Musa almatri的objc版本

 (void)viewWillLayoutSubviews { [super updateViewConstraints]; CGFloat desiredHeight = self.tableView.contentSize.height; // clamp desired height, if needed, and, in that case, leave scroll Enabled self.tableHeight.constant = desiredHeight; self.tableView.scrollEnabled = NO; } 

作为Anooj VM的答案的扩展,我build议以下内容只在更改时才更新内容大小。

这种方法也禁用正确的滚动 ,并支持更大的列表旋转 。 不需要dispatch_async,因为contentSize更改是在主线程上调度的。

 - (void)viewDidLoad { [super viewDidLoad]; [self.tableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:NULL]; } - (void)resizeTableAccordingToContentSize:(CGSize)newContentSize { CGRect superviewTableFrame = self.tableView.superview.bounds; CGRect tableFrame = self.tableView.frame; BOOL shouldScroll = newContentSize.height > superviewTableFrame.size.height; tableFrame.size = shouldScroll ? superviewTableFrame.size : newContentSize; [UIView animateWithDuration:0.3 delay:0 options:UIViewAnimationOptionCurveLinear animations:^{ self.tableView.frame = tableFrame; } completion: nil]; self.tableView.scrollEnabled = shouldScroll; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { if ([change[NSKeyValueChangeKindKey] unsignedIntValue] == NSKeyValueChangeSetting && [keyPath isEqualToString:@"contentSize"] && !CGSizeEqualToSize([change[NSKeyValueChangeOldKey] CGSizeValue], [change[NSKeyValueChangeNewKey] CGSizeValue])) { [self resizeTableAccordingToContentSize:[change[NSKeyValueChangeNewKey] CGSizeValue]]; } } - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { [super didRotateFromInterfaceOrientation:fromInterfaceOrientation]; [self resizeTableAccordingToContentSize:self.tableView.contentSize]; } - (void)dealloc { [self.tableView removeObserver:self forKeyPath:@"contentSize"]; } 
Interesting Posts