Eu tenho um UITableView
com cells
que são atualizadas dinamicamente. Tudo funciona bem, exceto quando o tableview.reload
é chamado (veja abaixo) para atualizar as cells
na tabela. Eu gostaria que a tabela rolasse para baixo para mostrar as novas inputs.
- (void)reloadTable:(NSNotification *)notification { NSLog(@"RELOAD TABLE ..."); [customTableView reloadData]; // Scroll to bottom of UITable here .... }
Eu estava planejando usar scrollToRowAtIndexPath:atScrollPosition:animated:
mas, em seguida, notei que não tenho access a um indexPath
.
Alguém sabe como fazer isso, ou de um retorno de chamada delegate
que eu poderia usar?
Usar:
NSIndexPath* ipath = [NSIndexPath indexPathForRow: cells_count-1 inSection: sections_count-1]; [tableView scrollToRowAtIndexPath: ipath atScrollPosition: UITableViewScrollPositionTop animated: YES];
Ou você pode especificar o índice de seção manualmente (Se uma seção => índice = 0).
-(void)scrollToBottom{ [self.tableView scrollRectToVisible:CGRectMake(0, self.tableView.contentSize.height - self.tableView.bounds.size.height, self.tableView.bounds.size.width, self.tableView.bounds.size.height) animated:YES]; }
Outra solução é virar a mesa verticalmente e virar cada célula verticalmente:
Aplique a transformação ao UITableView ao inicializar:
tableview.transform = CGAffineTransformMakeScale(1, -1);
e em cellForRowAtIndexPath:
cell.transform = CGAffineTransformMakeScale(1, -1);
Dessa forma, você não precisa de soluções alternativas para problemas de rolagem, mas precisará pensar um pouco mais sobre as interações do contentInsets / contentOffsets e do header / rodapé.
//In swift var iPath = NSIndexPath(forRow: self.tableView.numberOfRowsInSection(0)-1, inSection: self.tableView.numberOfSections()-1) self.tableView.scrollToRowAtIndexPath(iPath, atScrollPosition: UITableViewScrollPosition.Bottom, animated: true)
Esta é outra solução, funcionou bem no meu caso, quando a altura das células é grande.
- (void)scrollToBottom { CGPoint bottomOffset = CGPointMake(0, _bubbleTable.contentSize.height - _bubbleTable.bounds.size.height); if ( bottomOffset.y > 0 ) { [_bubbleTable setContentOffset:bottomOffset animated:YES]; } }
Como isso é algo que você pode querer usar com muita frequência, sugiro que você crie uma extensão de class no UITableView:
extension UITableView { func scrollToBottom(animated: Bool = true) { let section = self.numberOfSections if section > 0 { let row = self.numberOfRowsInSection(section - 1) if row > 0 { self.scrollToRowAtIndexPath(NSIndexPath(forRow: row - 1, inSection: section - 1), atScrollPosition: .Bottom, animated: animated) } } } }
É melhor fazer a extensão no UIScrollView em vez do UITableView, desta forma ele funciona em scrollView, tableView, collectionView (vertical), UIWebView (visualização de rolagem interna), etc.
public extension UIScrollView { public func scrollToBottom(animated animated: Bool) { let rect = CGRectMake(0, contentSize.height - bounds.size.height, bounds.size.width, bounds.size.height) scrollRectToVisible(rect, animated: animated) } }
Esse é o melhor caminho.
- (void)scrollToBottom { CGFloat yOffset = 0; if (self.tableView.contentSize.height > self.tableView.bounds.size.height) { yOffset = self.tableView.contentSize.height - self.tableView.bounds.size.height; } [self.tableView setContentOffset:CGPointMake(0, yOffset) animated:NO]; }
tente este código, pode ajudá-lo:
self.tableView.reloadData() DispatchQueue.main.asyncAfter(deadline: DispatchTime.now()+0.1, execute: { let indexPath = IndexPath(row: self.dateSource.count-1, section: 0) self.tableView.scrollToRow(at: indexPath, at: UITableViewScrollPosition.bottom, animated: true) })
Swift 3
Para todas as pessoas aqui tentando descobrir como resolver este problema, a chave é chamar o método .reloadData()
depois de .reloadData()
:
tableView.reloadData() tableView.layoutIfNeeded() tableView.setContentOffset(CGPoint(x: 0, y: tableView.contentSize.height - tableView.frame.height), animated: false)
Eu estava trabalhando com várias seções no UITableView
e funcionou bem.