Когда устанавливается UITableView contentSize?
У меня есть прокрутка UITableView
в UIScrollView
. Я установил размер кадра 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;
}
Кажется, что contentSize
в данный момент не обновляется. Если я вручную вычисляю фрейм в указанном выше методе на основе количества строк и разделов, то метод работает правильно.
Мой вопрос: как я могу получить UITableView
, чтобы обновить его contentSize
? Полагаю, я мог бы назвать reloadData
, и это, вероятно, сделало бы это, но кажется неэффективным перезагрузить всю таблицу, когда я просто вставляю одну ячейку.
Ответы
Ответ 1
Вы можете заставить UITableView рассчитать размер содержимого, вызвав layoutIfNeeded
в UITableView.
Пример для подкласса UITableViewController, который должен находиться в представлении контейнера с переменным размером:
- (CGSize)preferredContentSize
{
// Force the table view to calculate its height
[self.tableView layoutIfNeeded];
return self.tableView.contentSize;
}
Обновление 2016-07-28
Это непроверенный пример того же самого. Он должен работать, но если он не оставит комментария. Там могут быть более приятные или более идиоматические способы сделать это. К сожалению, я не очень хорошо знаком с Swift.
override var preferredContentSize: CGSize {
get {
self.tableView.layoutIfNeeded()
return self.tableView.contentSize
}
set {}
}
Ответ 2
В то время как я не люблю 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"];
}
Ответ 3
Попробуйте следующее:
- (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;
}
Ответ 4
-
Добавить наблюдателя (в моем примере в 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")
}
Ответ 5
Это сработало для меня, когда вы решаете проблемы с табличным представлением, получая правильный размер после добавления/удаления строк
Использование
tableView.layoutIfNeeded()
и установка
tableView.estimatedRowHeight = UITableViewAutomaticDimension
Ответ 6
Вы можете изменить рамки нижнего колонтитула. Я вызываю перед анимированным появлением нижнего колонтитула.
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)
}