Как оживить представление заголовка UITableView

Мне нужно анимировать вставку вида заголовка tableview. Я хочу, чтобы строки таблицы скользили вниз, в то время как представление заголовка расширяет рамки.
Пока что лучший результат, полученный с помощью следующего кода:

[self.tableView beginUpdates];  
[self.tableView setTableHeaderView:self.someHeaderView];  
[self.tableView endUpdates];

Проблема с этим решением заключается в том, что сам заголовок не анимируется, его кадр не расширяется.

Таким образом, эффект, который я получаю, заключается в том, что строки таблицы скользят вниз (как я хочу), но сразу отображается представление заголовка, и я хочу, чтобы он расширил его фрейм с анимацией.

Любые идеи?

Спасибо.

Ответ 1

имеют рамку заголовка в CGRectZero и установите его фрейм с помощью анимации

[self.tableView beginUpdates];  
[self.tableView setTableHeaderView:self.someHeaderView];  

[UIView animateWithDuration:.5f animations:^{
  CGRect theFrame = someBigger.frame;
  someHeaderView.frame = theFrame;
}];

[self.tableView endUpdates];  

Ответ 2

Вот что я получил для работы в Swift с начальной высотой кадра, равной нулю, и обновив ее до полной высоты при закрытии анимации:

// Calculate new frame size for the table header
var newFrame = tableView.tableHeaderView!.frame
newFrame.size.height = 42

// Get the reference to the header view
let tableHeaderView = tableView.tableHeaderView

// Animate the height change
UIView.animate(withDuration: 0.6) {
    tableHeaderView.frame = newFrame
    self.tableView.tableHeaderView = tableHeaderView
})

Ответ 3

Выбранный ответ не помог мне. Пришлось сделать следующее:

[UIView animateWithDuration: 0.5f
                 animations: ^{
                     CGRect frame = self.tableView.tableHeaderView.frame;
                     frame.size.height = self.headerViewController.preferredHeight;
                     self.tableView.tableHeaderView.frame = frame;
                     self.tableView.tableHeaderView = self.tableView.tableHeaderView;
                   }];

Поистине своеобразная часть заключается в том, что это работает в одном представлении, но не в подклассе той же иерархии контроллера представления/представления.

Ответ 4

Я нашел окончательный и правильный способ добиться реальной анимации на tableHeaderView s!

• Во-первых, если вы находитесь в Autolayout, сохраните систему Margin внутри своего заголовка. С Xcode 8 теперь это возможно (наконец!), Просто не устанавливайте никаких ограничений для любого из подзонов заголовка. Вам нужно будет определить правильные поля.

• Затем используйте beginUpdates и endUpdates, но поместите endUpdate в блок анимации.

// [self.tableView setTableHeaderView:headerView]; // not needed if already there
[self.tableView beginUpdates]; 
CGRect headerFrame = self.tableView.tableHeaderView.bounds;
headerFrame.size.height = PLAccountHeaderErrorHeight;

[UIView animateWithDuration:0.2 animations:^{
    self.tableView.tableHeaderView.bounds = headerFrame;

    [self.tableView endUpdates];
}];

Примечание. Я только пробовал в iOS10, я опубликую обновление, когда будет загружен мой симулятор iOS9.

ИЗМЕНИТЬ

К сожалению, он не работает в iOS9, а также в iOS10: сам заголовок не изменяет его высоту, но заголовок заголовка, похоже, перемещается, как если бы границы заголовков менялись.

Ответ 5

Решение SWIFT 4 с другим заголовком

Если вам нужна анимация такого типа, я использовал это решение: (хотя в моем случае мне также пришлось немного поиграть с непрозрачностью объектов, поскольку я загружал другой совершенно другой заголовок)

fileprivate func transitionExample() {

    let oldHeight = tableView.tableHeaderView?.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height ?? 0

    let newHeader = YourCustomHeaderView()
    newHeader.hideElements() // If you want to play with opacity.

    let smallHeaderFrame = CGRect(x: 0, y: 0, width: newHeader.frame.width, height: oldHeight)
    let fullHeaderFrame = newHeader.frame

    newHeader.frame = smallHeaderFrame

    UIView.animate(withDuration: 0.4) { [weak self] in
        self?.tableView.beginUpdates()
        newHeader.showElements() // Only if have hided the elements before.
        self?.tableView.tableHeaderView = newHeader
        self?.tableView.tableHeaderView?.frame = fullHeaderFrame
        self?.tableView.endUpdates()
    }
}

Итак, в основном, все дело в смене рамки внутри замыкания .animate. Обновления beging/end необходимы для перемещения и обновления других элементов tableView.

Ответ 6

Вот расширение Swift 5 UITableView для изменения headerView или изменения его высоты, анимированное с помощью AutoLayout

extension UITableView {

func animateTableHeader(view: UIView? = nil, frame: CGRect? = nil) {
    self.tableHeaderView?.setNeedsUpdateConstraints()
    UIView.animate(withDuration: 0.2, animations: {() -> Void in
        let hView = view ?? self.tableHeaderView
        if frame != nil {
            hView?.frame = frame!
        }
        self.tableHeaderView = hView
        self.tableHeaderView?.layoutIfNeeded()
    }, completion: nil)
}

}

Ответ 7

Используйте приведенный ниже код, это работает

extension UITableView {

 func hideTableHeaderView() -> Void {
    self.beginUpdates()
    UIView.animate(withDuration: 0.2, animations: {
        self.tableHeaderView = nil
    })
    self.endUpdates()
}

func showTableHeaderView(header: UIView) -> Void {
    let headerView = header
    self.beginUpdates()
    let headerFrame = headerView.frame
    headerView.frame = CGRect()
    self.tableHeaderView = headerView
    UIView.animate(withDuration: 0.2, animations: {
        self.tableHeaderView?.frame = headerFrame
        self.tableHeaderView?.alpha = 0
        self.endUpdates()
    }, completion: { (ok) in
        self.tableHeaderView?.alpha = 1
    })
   }
}