ios UITableView 的 contentSize 什么时候设置?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9958328/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
When does a UITableView's contentSize get set?
提问by Darren
I have a non scrolling UITableView
in a UIScrollView
. I set the frame size of the UITableView
to its content size.
我有一个非滚动UITableView
的UIScrollView
. 我将 的框架大小设置UITableView
为其内容大小。
When I add a row to the UITableView
, I call insertRowsAtIndexPaths:withRowAnimation
: on the UITableView
. Then I call a method to resize the frame of the UITableView
:
当我向 中添加一行时UITableView
,我调用insertRowsAtIndexPaths:withRowAnimation
: 在UITableView
. 然后我调用一个方法来调整框架的大小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;
}
It seems though that the contentSize
hasn't been updated at this point. If I manually calculate the frame in the above method based on the number of rows and sections, then the method works properly.
好像contentSize
目前还没有更新。如果我根据行数和节数手动计算上述方法中的框架,则该方法可以正常工作。
My question is, how can I get the UITableView
to update its contentSize
? I suppose I could call reloadData
and that would probably do it, but it seems inefficient to reload the entire table when I'm just inserting one cell.
我的问题是,我怎样才能UITableView
更新它的contentSize
?我想我可以打电话reloadData
,这可能会做到,但是当我只插入一个单元格时,重新加载整个表格似乎效率低下。
回答by felinira
You can force the UITableView to calculate the size of the content by calling layoutIfNeeded
on the UITableView.
您可以通过调用 UITableView 强制 UITableView 计算内容的大小layoutIfNeeded
。
Example for a UITableViewController subclass that should be in a container view with variable size:
UITableViewController 子类的示例,该子类应该位于具有可变大小的容器视图中:
- (CGSize)preferredContentSize
{
// Force the table view to calculate its height
[self.tableView layoutIfNeeded];
return self.tableView.contentSize;
}
Update 2016-07-28This is an untested Swift example of the same thing. It should work but if it doesn't please leave a comment. There might be nicer or more idiomatic ways to do this. Unfortunately I am not very familiar with Swift.
2016 年 7 月 28 日更新这是一个未经测试的 Swift 示例。它应该有效,但如果无效,请发表评论。可能有更好或更惯用的方法来做到这一点。不幸的是,我对 Swift 不是很熟悉。
override var preferredContentSize: CGSize {
get {
self.tableView.layoutIfNeeded()
return self.tableView.contentSize
}
set {}
}
回答by Brian Sachetta
While I don't love KVO (Key-Value Observing), it's a fairly good way to know exactly when your table's contentSize
has changed (rather than just calling your update methods in a bunch of random places). It's rather simple to use (though somewhat cryptic and implicit). To observe changes on your table's contentSize
, do the following:
虽然我不喜欢 KVO(键值观察),但它是准确知道表何时contentSize
发生更改的一种相当不错的方法(而不是仅仅在一堆随机位置调用更新方法)。它使用起来相当简单(虽然有些神秘和隐含)。要观察表的变化contentSize
,请执行以下操作:
1) Become an observer of your table's contentSize
property like so:
1)contentSize
像这样成为表属性的观察者:
[self.tableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:NULL];
This is usually done in the view controller that holds the tableView
(like in viewDidLoad:
, for example).
这通常在包含tableView
(例如 in viewDidLoad:
)的视图控制器中完成。
2) Implement the KVO observing method and make the changes you need:
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) Remove your view controller as an observer at some logical point (I call it in dealloc
). You do this like so:
3) 在某个逻辑点将您的视图控制器作为观察者移除(我称之为dealloc
)。你这样做:
- (void)dealloc {
[self.tableView removeObserver:self forKeyPath:@"contentSize"];
}
回答by rob mayoff
Try this:
尝试这个:
- (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;
}
回答by gbk
Add observer (in my sample in
viewDidLoad
tableView.addObserver(self, forKeyPath: "contentSize", options: .new, context: nil)
Observe value
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 } } } }
Remove observer when not needed
deinit { self.tableView.removeObserver(self, forKeyPath: "contentSize") }
添加观察者(在我的示例中
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") }
回答by Anil Kukadeja
as @Farthen suggested you should always call yourTableView.layoutIfNeeded() to recalculate content size first.
正如@Farthen 建议的那样,您应该始终先调用 yourTableView.layoutIfNeeded() 来重新计算内容大小。
By calling layoutIfNeeded UITableView will calculate contentSize again and then you can update the frame or constant whatever it is.
通过调用 layoutIfNeeded UITableView 将再次计算 contentSize,然后您可以更新框架或常量,无论它是什么。
Simple two line of code will save much more efforts.
简单的两行代码会省很多力。
tableView.layoutIfNeeded()
tableViewHeight.constant = tableView.contentSize.height
回答by Charles Bessonnet
You can change the frame of footer. I call before animated appear of footer.
您可以更改页脚的框架。我在页脚动画出现之前调用。
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)
}
回答by RiceAndBytes
This worked for me, when addressing the issues of the tableview getting the right size after adding / removing rows
这对我有用,在解决添加/删除行后 tableview 获得正确大小的问题时
Using
使用
tableView.layoutIfNeeded()
and setting
和设置
tableView.estimatedRowHeight = UITableViewAutomaticDimension