什么时候UITableView的contentSize被设置?
我在UIScrollView
有一个不滚动的UITableView
。 我将UITableView
的框架大小设置为其内容大小。
当我向UITableView
添加一行时,我在UITableView
调用了insertRowsAtIndexPaths:withRowAnimation
然后我调用一个方法来调整UITableView
的框架:
- (void)resizeTableViewFrameHeight { // Table view does not scroll, so its frame height should be equal to its contentSize height CGRect frame = self.tableView.frame; frame.size = self.tableView.contentSize; self.tableView.frame = frame; }
这似乎虽然contentSize
尚未更新在这一点上。 如果我手动计算框架在上面的方法基于行数和部分的数量,然后该方法正常工作。
我的问题是,我怎样才能让UITableView
更新其contentSize
? 我想我可以调用reloadData
,这可能会做到这一点,但是当我插入一个单元格时,重新加载整个表格似乎效率低下。
您可以强制UITableView通过调用UITableView上的layoutIfNeeded
来计算内容的大小。
一个UITableViewController子类的例子,它应该在容器视图中具有可变的大小:
- (CGSize)preferredContentSize { // Force the table view to calculate its height [self.tableView layoutIfNeeded]; return self.tableView.contentSize; }
更新2016-07-28这是一个未经testing的同样事情的Swift示例。 它应该工作,但如果它不请,请留下评论。 可能有更好或更习惯的方法来做到这一点。 不幸的是我对Swift不是很熟悉。
override var preferredContentSize: CGSize { get { self.tableView.layoutIfNeeded() return self.tableView.contentSize } set {} }
虽然我不喜欢KVO(Key-Value Observing),但是确实知道你的表的contentSize
发生了什么变化(而不是在一堆随机的地方调用你的更新方法)是一个相当好的方法。 它使用起来相当简单(虽然有点隐晦和隐含)。 要观察表的contentSize
上的更改,请执行以下操作:
1)成为你的表的contentSize
属性的观察者,如下所示:
[self.tableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:NULL];
这通常在保存tableView
的视图控制器(例如viewDidLoad:
)中完成。
2)执行KVO观测方法并进行所需的更改:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context { if(object == self.tableView && [keyPath isEqualToString:@"contentSize"]) { // perform your updates here } }
3)删除你的视图控制器作为观察者在某个逻辑点(我称之为dealloc
)。 你这样做是这样的:
- (void)dealloc { [self.tableView removeObserver:self forKeyPath:@"contentSize"]; }
尝试这个:
- (void)resizeTableViewFrameHeight { UITableView *tableView = self.tableView; CGRect frame = tableView.frame; frame.size.height = [tableView sizeThatFits:CGSizeMake(frame.size.width, HUGE_VALF)].height; tableView.frame = frame; }
-
添加观察者(在我的示例
viewDidLoad
tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
-
观察价值
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) { if let obj = object as? UITableView { if obj == self.tableView && keyPath == "contentSize" { if let newSize = change?[NSKeyValueChangeKey.newKey] as? CGSize { //do stuff here } } } }
-
不需要时移除观察者
deinit { self.tableView.removeObserver(self, forKeyPath: "contentSize") }
您可以更改页脚的框架。 我之前打电话animation出现的页脚。
if self.newTableView.contentSize.height < self.newTableView.frame.height { let additionalHeight: CGFloat = self.newTableView.frame.height - self.newTableView.contentSize.height let tableFooterView = self.newTableView.tableFooterView! let x = tableFooterView.frame.origin.x let y = tableFooterView.frame.origin.y + additionalHeight let width = tableFooterView.frame.width let height = tableFooterView.frame.height tableFooterView.frame = CGRect(x: x, y: y, width: width, height: height) }
这对我来说,解决在添加/删除行后得到正确大小的tableview的问题
运用
tableView.layoutIfNeeded()
和设置
tableView.estimatedRowHeight = UITableViewAutomaticDimension