Come avviare UITableView sull’ultima cella?

Nell’app Messaggi di Apple, quando si fa clic sul nome di un corrispondente e si passa alla visualizzazione tabella della conversazione (con palloncini per ciascun messaggio), la tabella viene visualizzata scorrendo fino alla fine. Nessuna animazione o niente, è solo lì.

Allo stesso modo, in Tweetie 2, quando carichi la vista tweet, sembra proprio dove l’hai guardata l’ultima volta. Nessuna animazione per arrivarci, è solo lì, come se nessuna delle celle sopra fosse caricata.

Come fanno queste app a fare questo? scrollToRowAtIndexPath:atScrollPosition:animated: da qualche parte nel controller della tabella? In tal caso, come fanno a sapere cosa passare a atScrollPosition: E in che modo si chiama?

scrollToRowAtIndexPath dovrebbe funzionare.

In viewWillAppear: prova questo:

 [theTableView reloadData]; NSIndexPath* ip = [NSIndexPath indexPathForRow:rowNumberHere inSection:sectionNumberHere]; [theTableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionTop animated:NO]; 

rowNumberHere è il numero di riga nell’origine dati a cui si desidera scorrere.

atScrollPosition è solo uno dei valori atScrollPosition UITableViewScrollPosition che può determinare dove sullo schermo verrà visualizzato il numero di riga desiderato. Tuttavia, a seconda del numero di righe e della riga a cui stai scorrendo, potrebbe non fare la differenza.

Mettere reloadData: evita un’eccezione se i dati non sono ancora stati caricati in viewWillAppear: Se metti lo scrollToRowAtIndexPath in viewDidAppear: non avrai bisogno del reloadData: ma vedrai la tabella saltare un po ‘che dici di non voler.

Modifica: @ Theory, prova a cambiare il tuo codice come segue …

 [tableView reloadData]; int lastRowNumber = [tableView numberOfRowsInSection:0] - 1; NSIndexPath* ip = [NSIndexPath indexPathForRow:lastRowNumber inSection:0]; [tableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionTop animated:NO]; 

Si noti che numberOfRowsInSection restituisce il conteggio delle righe, non l’ultimo numero di riga (che è il conteggio delle righe – 1).

È ansible chiamare -scrollToRowAtIndexPath: atScrollPosition: animato all’interno di -viewWillAppear: metodo del TableViewController.

atScrollPosition: consente di impostare dove si desidera che la cella venga visualizzata per rowAtIndexPath. Ci sono quattro opzioni:

UITableViewScrollPositionTop – mette la tua cella proprio nella parte superiore della vista

UITableViewScrollPositionMiddle : centra la cella nella vista

UITableViewScrollPositionBottom – pone la cella in basso

UITableViewScrollPositionNone : l’utilizzo di questa impostazione si posiziona nella cella nella visualizzazione utente con scorrimento / spostamento minimi.

Il comportamento è diverso in tre scenari: –

Se la cella è già in vista, non fa nulla.

Se la cella è sopra la vista corrente, scorre la cella nella parte superiore della vista.

Se la cella si trova al di sotto della vista corrente, scorre la cella nella parte inferiore della vista.

Seguendo la risposta di DyingCactus sopra, ho aggiunto questo metodo al mio controller:

 -(void)viewWillAppear:(BOOL)animated { [self.tableView reloadData]; NSIndexPath* ip = [NSIndexPath indexPathForRow:[self.tableView numberOfRowsInSection:0] - 1 inSection:0]; [self.tableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionTop animated:NO]; } 

E ora funziona, esattamente quello che volevo. Grazie!

Sto usando l’autolayout e nessuna delle risposte ha funzionato per me. Ecco la mia soluzione che finalmente ha funzionato:

 @property (nonatomic, assign) BOOL shouldScrollToLastRow; - (void)viewDidLoad { [super viewDidLoad]; _shouldScrollToLastRow = YES; } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; // Scroll table view to the last row if (_shouldScrollToLastRow) { _shouldScrollToLastRow = NO; [self.tableView setContentOffset:CGPointMake(0, CGFLOAT_MAX)]; } } 

Risposta di @DyingCactus in Swift 3 :

  let lastRow: Int = self.tableView.numberOfRows(inSection: 0) - 1 let indexPath = IndexPath(row: lastRow, section: 0); self.tableView.scrollToRow(at: indexPath, at: .top, animated: false) 

Il problema con il metodo scrollToRowAtIndexPath è lento e la tabellaView richiede tempo per scorrere verso il basso.

Ho avuto lo stesso identico problema, dopo aver provato tutto (come te), questo ha funzionato, la chiave è che se stai usando l’autolayout inizializza scrollToBottom su true e poi fai questo

 - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; // Scroll table view to the last row [self scrollToBottom]; } -(void)scrollToBottom { if (shouldScrollToLastRow) { CGPoint bottomOffset = CGPointMake(0, self.tableView.contentSize.height - self.tableView.bounds.size.height); [self.tableView setContentOffset:bottomOffset animated:NO]; } } 

facendo ciò ti assicurerai di essere quasi in fondo al tuo tavoloView ma potrebbe non essere in fondo perché è imansible conoscere l’esatto offset di fondo quando sei in cima alla tabellaView, quindi dopo possiamo implementare scrollViewDidScroll

 -(void)scrollViewDidScroll: (UIScrollView*)scrollView { float scrollViewHeight = scrollView.frame.size.height; float scrollContentSizeHeight = scrollView.contentSize.height; float scrollOffset = scrollView.contentOffset.y; // if you're not at bottom then scroll to bottom if (!(scrollOffset + scrollViewHeight == scrollContentSizeHeight)) { [self scrollToBottom]; } else { // bottom reached now stop scrolling shouldScrollToLastRow = false; } } 

Nota per scorrere alla riga inferiore, la sezione deve essere l’ultima sezione non 0 (prima sezione):

 int lastSection = [self.myTableView numberOfSections] -1; if (lastSection < 0) return; int lastRow = [self.myTableView numberOfRowsInSection:lastSection] - 1; if (lastRow < 0) return; NSIndexPath* ip = [NSIndexPath indexPathForRow:lastRow inSection:lastSection]; [self.myTableView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionTop animated:YES]; 
 #import "ViewController.h" @interface ViewController () @end @implementation ViewController CGFloat labelWidth = 260.0f; CGFloat labelRequiredHeight = 180.0f; @synthesize tblView; @synthesize txtField; @synthesize chatData; - (void)viewDidLoad { [super viewDidLoad]; tblView.delegate = self; [self.tblView setSeparatorStyle:UITableViewCellSeparatorStyleNone]; chatData = [[NSMutableArray alloc] init]; [self registerForKeyboardNotifications]; } -(IBAction) textFieldDoneEditing : (id) sender { NSLog(@"the text content%@",txtField.text); [sender resignFirstResponder]; [txtField resignFirstResponder]; } - (IBAction)sendButton:(id)sender { if (txtField.text.length>0) { // updating the table immediately NSArray *data = [NSArray arrayWithObject:@"text"]; NSArray *objects = [NSArray arrayWithObject:txtField.text]; NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects forKeys:data]; [chatData addObject:dictionary]; NSMutableArray *insertIndexPaths = [[NSMutableArray alloc] init]; NSIndexPath *newPath = [NSIndexPath indexPathForRow:0 inSection:0]; [insertIndexPaths addObject:newPath]; [tblView beginUpdates]; [tblView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationTop]; [tblView endUpdates]; [tblView reloadData]; txtField.text = @""; [self.view endEditing:YES]; } } -(IBAction) backgroundTap:(id) sender { [self.txtField resignFirstResponder]; } -(BOOL)SendbtnShouldReturn:(UITextField *)textfield { [textfield resignFirstResponder]; return YES; } - (BOOL)textFieldShouldReturn:(UITextField *)textField { NSLog(@"the text content%@",txtField.text); [textField resignFirstResponder]; if (txtField.text.length>0) { // updating the table immediately NSArray *keys = [NSArray arrayWithObject:@"text"]; NSArray *objects = [NSArray arrayWithObject:txtField.text]; NSDictionary *dictionary = [NSDictionary dictionaryWithObjects:objects forKeys:keys]; [chatData addObject:dictionary]; NSMutableArray *insertIndexPaths = [[NSMutableArray alloc] init]; NSIndexPath *newPath = [NSIndexPath indexPathForRow:0 inSection:0]; [insertIndexPaths addObject:newPath]; [tblView beginUpdates]; [tblView insertRowsAtIndexPaths:insertIndexPaths withRowAnimation:UITableViewRowAnimationTop]; [tblView endUpdates]; [tblView reloadData]; txtField.text = @""; } return NO; } // Keyboard Functionality -(void) registerForKeyboardNotifications { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWasShown:) name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; } -(void) freeKeyboardNotifications { [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil]; [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillHideNotification object:nil]; } -(void) keyboardWasShown:(NSNotification*)aNotification { NSLog(@"Keyboard was shown"); NSDictionary* info = [aNotification userInfo]; // Get animation info from userInfo NSTimeInterval animationDuration; UIViewAnimationCurve animationCurve; CGRect keyboardFrame; [[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve]; [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration]; [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] getValue:&keyboardFrame]; // Move [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:animationDuration]; [UIView setAnimationCurve:animationCurve]; NSLog(@"frame..%f..%f..%f..%f",self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height); NSLog(@"keyboard..%f..%f..%f..%f",keyboardFrame.origin.x, keyboardFrame.origin.y, keyboardFrame.size.width, keyboardFrame.size.height); [self.view setFrame:CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y- keyboardFrame.size.height, self.view.frame.size.width, self.view.frame.size.height)]; [tblView setFrame:CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y+ keyboardFrame.size.height, self.view.frame.size.width, self.view.frame.size.height-keyboardFrame.size.height)]; [tblView scrollsToTop]; [UIView commitAnimations]; } -(void) keyboardWillHide:(NSNotification*)aNotification { NSLog(@"Keyboard will hide"); NSDictionary* info = [aNotification userInfo]; // Get animation info from userInfo NSTimeInterval animationDuration; UIViewAnimationCurve animationCurve; CGRect keyboardFrame; [[info objectForKey:UIKeyboardAnimationCurveUserInfoKey] getValue:&animationCurve]; [[info objectForKey:UIKeyboardAnimationDurationUserInfoKey] getValue:&animationDuration]; [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] getValue:&keyboardFrame]; // Move [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:animationDuration]; [UIView setAnimationCurve:animationCurve]; [self.view setFrame:CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y + keyboardFrame.size.height, self.view.frame.size.width, self.view.frame.size.height)]; [tblView setFrame:CGRectMake(self.view.frame.origin.x, self.view.frame.origin.y, self.view.frame.size.width, self.view.frame.size.height)]; [UIView commitAnimations]; UIEdgeInsets contentInsets = UIEdgeInsetsZero; self.tblView.contentInset = contentInsets; self.tblView.scrollIndicatorInsets = contentInsets; self.tblView.scrollEnabled=chatData; } #pragma mark UITableViewDataSource protocol methods - (void)scrollTableToBottom { int rowNumber = [self.tblView numberOfRowsInSection:1]; if (rowNumber > 0) [self.tblView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:rowNumber-1 inSection:0] atScrollPosition:UITableViewScrollPositionBottom animated:YES]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [chatData count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *[email protected]"chatCell"; chatCell *cell = (chatCell *)[tableView dequeueReusableCellWithIdentifier: @"chatCellIdentifier"]; if(!cell) cell =[[chatCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier]; // NSUInteger row = [chatData count]-[indexPath row]-1; NSUInteger row=[indexPath row]; NSUInteger count = [chatData count]; if (row  self.tblView.frame.size.height) // { // [self.tblView scrollToRowAtIndexPath:[self. indexPathForLastMessage] // atScrollPosition:UITableViewScrollPositionBottom animated:YES]; // } //} -(void)viewWillAppear:(BOOL)animated { // [tblView reloadData]; // // int lastRowNumber = [tblView numberOfRowsInSection:0] - 1; // NSIndexPath* ip = [NSIndexPath indexPathForRow:lastRowNumber inSection:0]; // [tblView scrollToRowAtIndexPath:ip atScrollPosition:UITableViewScrollPositionTop animated:NO]; } -(void)viewDidAppear:(BOOL)animated { //[tblView reloadData]; } - (void)reloadTableViewDataSource { [tblView reloadData]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; // Dispose of any resources that can be recreated. } @end