Estou tendo problemas para resize um tableHeaderView. Simples não funciona.
1) Crie um UITableView e UIView (100 x 320 px);
2) Defina o UIView como tableHeaderView do UITableView;
3) Construa e vá. Está tudo bem.
Agora, quero resize o tableHeaderView, então incluo esse código no 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;
A altura da tableHeaderView deve aparecer com 200, mas aparece com 100.
Se eu escrever:
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;
Então começa com 200 de altura, como eu quero. Mas eu quero poder modificá-lo em tempo de execução.
Eu também tentei isso sem sucesso:
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];
O ponto aqui é: Como redimensionamos um tableHeaderView em runtime ???
Alguém consegue fazer isso?
obrigado
iMe
FYI: Eu consegui isso para funcionar modificando o tableHeaderView e re-definindo-o. Nesse caso, estou ajustando o tamanho do tableHeaderView quando a subvisão UIWebView terminar de carregar.
[webView sizeToFit]; CGRect newFrame = headerView.frame; newFrame.size.height = newFrame.size.height + webView.frame.size.height; headerView.frame = newFrame; [self.tableView setTableHeaderView:headerView];
Esta resposta é antiga e aparentemente não funciona no iOS 7 e acima.
Eu corri para o mesmo problema, e eu também queria que as mudanças fossem animadas, então criei uma subclass de UIView para minha visualização de header e adicionei estes methods:
- (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]; }
Essencialmente, isso anima todas as subvisualizações do UITableView que não são do mesmo tipo de class que a class chamadora. No final da animação, ele chama setTableHeaderView no superview (o UITableView) – sem isso, o conteúdo do UITableView retornará na próxima vez que o usuário rolar. A única limitação que encontrei até agora é que, se o usuário tentar rolar o UITableView enquanto a animação estiver ocorrendo, a rolagem será animada como se a visualização do header não tivesse sido redimensionada (não é grande coisa se a animação for rápido).
Se você quiser animar condicionalmente as alterações, faça o seguinte:
- (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]; } }
Por favor, note que a animação é bidirecional:
tableHeaderView
. Isso é feito usando beginUpdates
e endUpdates
UIView
. A fim de sincronizar essas duas animações, o animationCurve
tem que ser configurado para UIViewAnimationCurveEaseInOut
e a duração para 0.3
, que parece ser o que o UITableView usa para sua animação.
Eu criei um projeto Xcode no gihub, que faz isso. Confira o projeto ResizeTableHeaderViewAnimated
in besi / ios-quickies
Eu acho que deve funcionar se você apenas definir a altura do myHeaderView da seguinte forma:
CGRect newFrame = myHeaderView.frame; newFrame.size.height = newFrame.size.height + 100; myHeaderView.frame = newFrame; self.tableView.tableHeaderView = myHeaderView;
Usei a solução @garrettmoon acima até o iOS 7.
Aqui está uma solução atualizada baseada em @ 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]; }
Isso funcionou para mim no iOS 7 e 8. Esse código está sendo executado no controlador de exibição de tabela.
[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]; }];
É porque o setter de tableHeaderView.
Você precisa definir a altura do UIView antes de definir o tableHeaderView. (Seria muito mais fácil se a Apple abrir fonts deste framework …)
No iOS 9 e abaixo, tableHeaderView
não seria re-layout após redimensioná-lo. Esse problema foi resolvido no iOS 10.
Para resolver este problema, basta fazê-lo com o seguinte código:
self.tableView.tableHeaderView = self.tableView.tableHeaderView;
No iOS 9.x, fazer isso no viewDidLoad
funciona muito bem:
var frame = headerView.frame frame.size.height = 11 // New size headerView.frame = frame
headerView
é declarado como @IBOutlet var headerView: UIView!
e conectado no storyboard, onde é colocado no topo do tableView, para funcionar como tableHeaderView.
Definir a altura para a propriedade de exibição de header tableView.tableHeaderView
no viewDidLoad
não parece funcionar, a altura da exibição de header ainda não é alterada conforme o esperado.
Depois de lutar contra esse problema por muitas tentativas. Descobri que, você pode alterar a altura invocando a lógica de criação da visualização de header dentro do método - (void)didMoveToParentViewController:(UIViewController *)parent
.
Então, o código de exemplo ficaria assim:
- (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]; } }
Eu encontrei o inicializador initWithFrame de um UIView não homenageia corretamente o rect eu passar dentro Por isso, eu fiz o seguinte, que funcionou perfeitamente:
- (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); // ... } }
A vantagem disso é que é melhor encapsulado em seu código de visualização.
Eu implementei a mudança de altura animada do header da tabela para expandir para a canvas geral quando tocada. No entanto, o código pode ajudar em outros casos:
// 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 }
Eu queria um UITableView
com um UISearchBar
como o header para a tabela, então eu tenho uma hierarquia que se parece com isso
UITableView | |--> UIView | |--> UISearchBar | |--> UITableViewCells
Como foi dito em outro lugar, se você não definir o TableViewHeader após alterá-lo, nada acontecerá.
- (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; }
Se o costume headerView for projetado usando o autolayout e o headerView precisar ser atualizado após a busca da Web ou uma tarefa preguiçosa semelhante. então no iOS-Swift eu fiz isso e atualizei o meu headerView usando o seguinte código:
//to reload your cell data self.tableView.reloadData() dispatch_async(dispatch_get_main_queue(),{ // this is needed to update a specific tableview's headerview layout on main queue otherwise it's won't update perfectly cause reloaddata() is called self.tableView.beginUpdates() self.tableView.endUpdates() }
Obviamente, até agora a Apple deveria ter implementado o UITableViewAutomaticDimension para tableHeaderView & tableFooterView …
O seguinte parece funcionar para mim usando a (s) restrição (ões) do layout:
CGSize s = [ self systemLayoutSizeFittingSize : UILayoutFittingCompressedSize ]; CGRect f = [ self frame ]; f.size = s; [ self setFrame : f ];
Você tentou [self.tableView reloadData]
depois de alterar a altura?