Как изменить размер таблицыHeaderView UITableView?

У меня проблема с изменением размера tableHeaderView. Это просто не работает.

1) Создайте UITableView и UIView (100 x 320 пикселей);

2) Установите UIView как tableHeaderView для UITableView;

3) Постройте и идите. Все в порядке.

Теперь я хочу изменить размер таблицыHeaderView, поэтому я добавляю этот код в viewDidLoad:

self.tableView.autoresizesSubviews = YES;

self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;

CGRect newFrame = self.tableView.tableHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
self.tableView.tableHeaderView.frame = newFrame;

Высота таблицыHeaderView должна появиться с 200, но появится со 100.

Если я пишу:

self.tableView.autoresizesSubviews = YES;


CGRect newFrame = myHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
myHeaderView.frame = newFrame;


self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;

Затем он начинается с 200 высоты, как я хочу. Но я хочу иметь возможность изменять его во время выполнения.

Я также пробовал это без успеха:

self.tableView.autoresizesSubviews = YES;

self.tableView.tableHeaderView = myHeaderView;
self.tableView.tableFooterView = myFooterView;

CGRect newFrame = self.tableView.tableHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
self.tableView.tableHeaderView.frame = newFrame;

[self.tableView.tableHeaderView setNeedsLayout];
[self.tableView.tableHeaderView setNeedsDisplay];
[self.tableView setNeedsLayout];
[self.tableView setNeedsDisplay];

Пункт здесь: Как изменить размер таблицыHeaderView во время выполнения???

Кто-нибудь может это сделать?

Спасибо

IME

Ответ 1

FYI: Я получил это для работы, изменив tableHeaderView и переустановив его. В этом случае я настраиваю размер tableHeaderView, когда подвью UIWebView завершил загрузку.

[webView sizeToFit];
CGRect newFrame = headerView.frame;
newFrame.size.height = newFrame.size.height + webView.frame.size.height;
headerView.frame = newFrame;
[self.tableView setTableHeaderView:headerView];

Ответ 2

Этот ответ старый и, по-видимому, не работает на iOS 7 и выше.

Я столкнулся с той же проблемой, и мне также нужны изменения для анимации, поэтому я создал подкласс UIView для моего заголовка и добавил эти методы:

- (void)adjustTableHeaderHeight:(NSUInteger)newHeight{
    NSUInteger oldHeight = self.frame.size.height;
    NSInteger originChange = oldHeight - newHeight;

    [UIView beginAnimations:nil context:nil];

    [UIView setAnimationDuration:1.0f];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];

    self.frame = CGRectMake(self.frame.origin.x, 
                        self.frame.origin.y, 
                        self.frame.size.width, 
                        newHeight);

    for (UIView *view in [(UITableView *)self.superview subviews]) {
        if ([view isKindOfClass:[self class]]) {
            continue;
        }
        view.frame = CGRectMake(view.frame.origin.x, 
                            view.frame.origin.y - originChange, 
                            view.frame.size.width, 
                            view.frame.size.height);
    }

    [UIView commitAnimations];
}

- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context{
    [(UITableView *)self.superview setTableHeaderView:self];
}

Это по существу анимирует все подпрограммы UITableView, которые не являются тем же типом класса, что и вызывающий класс. В конце анимации он вызывает setTableHeaderView в супервизии (UITableView) - без этого содержимое UITableView будет отскакивать при следующем прокрутке пользователя. Единственное ограничение, которое я нашел на этом до сих пор, заключается в том, что если пользователь пытается прокрутить UITableView во время анимации, прокрутка будет анимировать, как если бы вид заголовка не был изменен (неважно, если анимация быстро).

Ответ 3

Если вы хотите условно анимировать изменения, вы можете сделать следующее:

- (void) showHeader:(BOOL)show animated:(BOOL)animated{

    CGRect closedFrame = CGRectMake(0, 0, self.view.frame.size.width, 0);
    CGRect newFrame = show?self.initialFrame:closedFrame;

    if(animated){
        // The UIView animation block handles the animation of our header view
        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:0.3];
        [UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];

        // beginUpdates and endUpdates trigger the animation of our cells
        [self.tableView beginUpdates];
    }

    self.headerView.frame = newFrame;
    [self.tableView setTableHeaderView:self.headerView];

    if(animated){
        [self.tableView endUpdates];
        [UIView commitAnimations];
    }
}

Обратите внимание, что анимация состоит из двух слоёв:

  • Анимация ячеек ниже tableHeaderView. Это делается с помощью beginUpdates и endUpdates
  • Анимация фактического заголовка. Это делается с помощью блока анимации UIView.

Чтобы синхронизировать эти две анимации, значение animationCurve должно быть установлено на UIViewAnimationCurveEaseInOut, а продолжительность - на 0.3, что, по-видимому, соответствует UITableView для анимации.

Update

Я создал проект Xcode на gihub, который делает это. Проверьте проект ResizeTableHeaderViewAnimated в besi/ios-quickies

screenshot

Ответ 4

Я думаю, что он должен работать, если вы просто установите высоту myHeaderView так:

CGRect newFrame = myHeaderView.frame;
newFrame.size.height = newFrame.size.height + 100;
myHeaderView.frame = newFrame;

self.tableView.tableHeaderView = myHeaderView;

Ответ 5

Используется решение @garrettmoon выше до iOS 7.
Здесь обновленное решение, основанное на @garrettmoon's:

- (void)adjustTableHeaderHeight:(NSUInteger)newHeight animated:(BOOL)animated {

    [UIView beginAnimations:nil context:nil];

    [UIView setAnimationDuration:[CATransaction animationDuration]];
    [UIView setAnimationDelegate:self];
    [UIView setAnimationDidStopSelector:@selector(animationDidStop:finished:context:)];

    self.frame = CGRectMake(self.frame.origin.x,
                        self.frame.origin.y,
                        self.frame.size.width,
                        newHeight);

    [(UITableView *)self.superview setTableHeaderView:self];

    [UIView commitAnimations];
}

- (void)animationDidStop:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context{
    [(UITableView *)self.superview setTableHeaderView:self];
}

Ответ 6

Это работало для меня на iOS 7 и 8. Этот код работает на контроллере табличного представления.

[UIView animateWithDuration:0.3 animations:^{
    CGRect oldFrame = self.headerView.frame;
    self.headerView.frame = CGRectMake(oldFrame.origin.x, oldFrame.origin.y, oldFrame.size.width, newHeight);
    [self.tableView setTableHeaderView:self.headerView];
}];

Ответ 7

Это потому, что установщик tableHeaderView.

Вы должны установить высоту UIView перед установкой tableHeaderView. (Было бы намного проще, если бы Apple открыла исходники этой структуры...)

Ответ 8

В iOS 9.x выполнение этого на viewDidLoad выполняется просто:

var frame = headerView.frame
frame.size.height = 11  // New size
headerView.frame = frame

headerView объявляется как @IBOutlet var headerView: UIView! и подключен к раскадровке, где он помещается в верхней части таблицыView, чтобы функционировать как tableHeaderView.

Ответ 9

В iOS 9 и ниже tableHeaderView не будет повторно размещаться после изменения размера. Эта проблема разрешена в iOS 10.

Чтобы решить эту проблему, просто сделайте это со следующим кодом:

self.tableView.tableHeaderView = self.tableView.tableHeaderView;

Ответ 10

Настройка свойства высота для заголовка заголовка tableView.tableHeaderView в viewDidLoad кажется неработоспособной, высота представления заголовка по-прежнему не изменяется, как ожидалось.

После борьбы с этой проблемой для многих попыток. Я обнаружил, что вы можете изменить высоту, вызвав логику создания представления заголовка внутри - (void)didMoveToParentViewController:(UIViewController *)parent.

Итак, пример кода будет выглядеть так:

- (void)didMoveToParentViewController:(UIViewController *)parent {
    [super didMoveToParentViewController:parent];

    if ( _tableView.tableHeaderView == nil ) {
        UIView *header = [[[UINib nibWithNibName:@"your header view" bundle:nil] instantiateWithOwner:self options:nil] firstObject];

        header.frame = CGRectMake(0, 0, CGRectGetWidth([UIScreen mainScreen].bounds), HeaderViewHeight);

        [_tableView setTableHeaderView:header];
    }
}

Ответ 11

Я обнаружил, что инициализатор initWithFrame в UIView неправильно соблюдает адрес, который я передаю. Следовательно, я сделал следующее, которое отлично работало:

 - (id)initWithFrame:(CGRect)aRect {

    CGRect frame = [[UIScreen mainScreen] applicationFrame];

    if ((self = [super initWithFrame:CGRectZero])) {

        // Ugly initialization behavior - initWithFrame will not properly honor the frame we pass
        self.frame = CGRectMake(0, 0, frame.size.width, 200);

        // ...
    }
}

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

Ответ 12

Я реализовал анимированное изменение высоты заголовка таблицы, чтобы развернуть его до общего экрана при нажатии. Однако код может помочь в других случаях:

// Swift
@IBAction func tapped(sender: UITapGestureRecognizer) {

    self.tableView.beginUpdates()       // Required to update cells. 

    // Collapse table header to original height
    if isHeaderExpandedToFullScreen {   

        UIView.animateWithDuration(0.5, animations: { () -> Void in
            self.scrollView.frame.size.height = 110   // original height in my case is 110
        })

    }
    // Expand table header to overall screen            
    else {      
        let screenSize = self.view.frame           // "screen" size

        UIView.animateWithDuration(0.5, animations: { () -> Void in
            self.scrollView.frame.size.height = screenSize.height
        })
    }

    self.tableView.endUpdates()  // Required to update cells. 

    isHeaderExpandedToFullScreen= !isHeaderExpandedToFullScreen  // Toggle
}

Ответ 13

UITableView изменение размера заголовка - UISearchBar с панелью охвата

Мне нужен UITableView с UISearchBar как заголовок таблицы, поэтому у меня есть иерархия, которая выглядит как

UITableView
  |
  |--> UIView
  |     |--> UISearchBar
  |
  |--> UITableViewCells

Методы UISearchBarDelegate

Как уже было сказано в другом месте, если вы не установили TableViewHeader после его изменения, ничего не произойдет.

- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
    searchBar.showsScopeBar = YES;
    [UIView animateWithDuration:0.2f animations:^{
        [searchBar sizeToFit];
        CGFloat height = CGRectGetHeight(searchBar.frame);

        CGRect frame = self.tableView.tableHeaderView.frame;
        frame.size.height = height;
        self.tableHeaderView.frame = frame;
        self.tableView.tableHeaderView = self.tableHeaderView;
    }];

    [searchBar setShowsCancelButton:YES animated:YES];
    return YES;
}

- (BOOL)searchBarShouldEndEditing:(UISearchBar *)searchBar
{
    searchBar.showsScopeBar = NO;
    [UIView animateWithDuration:0.f animations:^{
        [searchBar sizeToFit];

        CGFloat height = CGRectGetHeight(searchBar.frame);

        CGRect frame = self.tableView.tableHeaderView.frame;
        frame.size.height = height;
        self.tableHeaderView.frame = frame;
        self.tableView.tableHeaderView = self.tableHeaderView;
    }];

    [searchBar setShowsCancelButton:NO animated:YES];
    return YES;
}

Ответ 14

Если пользовательский заголовок ViewView создан с использованием автозапуска, а headerView необходимо обновить после веб-выборки или аналогичной ленивой задачи. затем в iOS-Swift я сделал это и получил обновленный заголовочный файл, используя следующий код:

//to reload your cell data
self.tableView.reloadData()
dispatch_async(dispatch_get_main_queue(),{
// this is needed to update a specific tableview headerview layout on main queue otherwise it won't update perfectly cause reloaddata() is called
  self.tableView.beginUpdates()
  self.tableView.endUpdates()
} 

Ответ 15

Вы пытались [self.tableView reloadData] после изменения высоты?