Подтвердить что ты не робот

Когда устанавливается 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, и это, вероятно, сделало бы это, но кажется неэффективным перезагрузить всю таблицу, когда я просто вставляю одну ячейку.

4b9b3361

Ответ 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)
    }