2010-12-04 2 views
30

Это является продолжением до How to get notified when a tableViewController finishes animating the push onto a nav stack.Как получить уведомление, когда scrollToRowAtIndexPath заканчивает анимировать

В tableView Я хочу, чтобы отменить строку с анимацией, но только после того, как Tableview имеет закончил оживляющий свиток выбранный ряд. Как я могу получить уведомление, когда это произойдет, или какой метод вызывается в момент завершения.

Это порядок вещей:

  1. вид Нажмите контроллер
  2. В viewWillAppear я выбираю определенную строку.
  3. В viewDidAppear I scrollToRowAtIndexPath (к выбранной строке).
  4. Тогда, когда это заканчивается прокрутки Я хочу deselectRowAtIndexPath: animated:YES

Таким образом, пользователь будет знать, почему они прокручиваются, но тогда я могу исчезнуть выбор.
Шаг 4 - это часть, которую я еще не понял. Если я назову его в viewDidAppear, то к тому моменту, когда прокрутится таблицаViewView, строка уже отменена, и это не хорошо.

ответ

56

Вы можете использовать метод делегата таблицы scrollViewDidEndScrollingAnimation:. Это связано с тем, что UITableView является подклассом UIScrollView и UITableViewDelegate соответствует UIScrollViewDelegate. Другими словами, представление таблицы представляет собой представление прокрутки, а делегат представления таблицы также является делегатом представления прокрутки.

Итак, создайте метод scrollViewDidEndScrollingAnimation: в вашем представлении представления таблицы и отмените выбор ячейки в этом методе. Информацию о методе scrollViewDidEndScrollingAnimation: см. В справочной документации для UIScrollViewDelegate.

+0

Еще раз спасибо! – Andrew 2010-12-04 23:28:39

+0

Добро пожаловать. – 2010-12-04 23:34:45

+41

Было бы неплохо, если бы iOS предоставила версию с блоком завершения (например, «UIView animateWithDuration: анимация: завершение»), поэтому уведомление может быть контекстно-зависимым ... – pixelfreak 2011-12-09 22:09:10

11

Чтобы прокомментировать комментарий Бена Паккарда относительно принятого ответа, вы можете это сделать. Проверьте, может ли tableView перейти к новой позиции. Если нет, немедленно выполните свой метод. Если он может прокручиваться, дождитесь завершения прокрутки для выполнения вашего метода.

- (void)someMethod 
{ 
    CGFloat originalOffset = self.tableView.contentOffset.y; 
    [self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionMiddle animated:NO]; 
    CGFloat offset = self.tableView.contentOffset.y; 

    if (originalOffset == offset) 
    { 
     // scroll animation not required because it's already scrolled exactly there 
     [self doThingAfterAnimation]; 
    } 
    else 
    { 
     // We know it will scroll to a new position 
     // Return to originalOffset. animated:NO is important 
     [self.tableView setContentOffset:CGPointMake(0, originalOffset) animated:NO]; 
     // Do the scroll with animation so `scrollViewDidEndScrollingAnimation:` will execute 
     [self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionMiddle animated:YES]; 
    } 
} 

- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView 
{ 
    [self doThingAfterAnimation]; 
} 
8

Вы можете включить scrollToRowAtIndexPath: внутри [UIView animateWithDuration:...] блока, который будет запускать блок завершения после того, как все включено анимация заканчивается. Так, что-то вроде этого:

[UIView 
    animateWithDuration:0.3f 
    delay:0.0f 
    options:UIViewAnimationOptionAllowUserInteraction 
    animations:^ 
    { 
     // Scroll to row with animation 
     [self.tableView scrollToRowAtIndexPath:indexPath 
          atScrollPosition:UITableViewScrollPositionTop 
            animated:YES]; 
    } 
    completion:^(BOOL finished) 
    { 
     // Deselect row 
     [self.tableView deselectRowAtIndexPath:indexPath animated:YES]; 
    }]; 
28

попробовать это

[UIView animateWithDuration:0.3 animations:^{ 
    [yourTableView scrollToRowAtIndexPath:indexPath 
         atScrollPosition:UITableViewScrollPositionTop 
           animated:NO]; 
} completion:^(BOOL finished){ 
    //do something 
}]; 

Не забудьте установить анимированные НЕТ, анимация scrollToRow будет отменено UIView animateWithDuration.

Надеюсь, что эта помощь!

0

Реализация этого в Быстрое расширение.

//strong ref required 
private var lastDelegate : UITableViewScrollCompletionDelegate! = nil 

private class UITableViewScrollCompletionDelegate : NSObject, UITableViewDelegate { 
    let completion:() ->() 
    let oldDelegate : UITableViewDelegate? 
    let targetOffset: CGPoint 
    @objc private func scrollViewDidEndScrollingAnimation(scrollView: UIScrollView) { 
     scrollView.delegate = oldDelegate 
     completion() 
     lastDelegate = nil 
    } 

    init(completion:() ->(), oldDelegate: UITableViewDelegate?, targetOffset: CGPoint) { 
     self.completion = completion 
     self.oldDelegate = oldDelegate 
     self.targetOffset = targetOffset 
     super.init() 
     lastDelegate = self 
    } 
} 

extension UITableView { 
    func scrollToRowAtIndexPath(indexPath: NSIndexPath, atScrollPosition scrollPosition: UITableViewScrollPosition, animated: Bool, completion:() ->()) { 
     assert(lastDelegate == nil, "You're already scrolling. Wait for the last completion before doing another one.") 
     let originalOffset = self.contentOffset 
     self.scrollToRowAtIndexPath(indexPath, atScrollPosition: scrollPosition, animated: false) 

     if originalOffset.y == self.contentOffset.y { //already at the right position 
      completion() 
      return 
     } 
     else { 
      let targetOffset = self.contentOffset 
      self.setContentOffset(originalOffset, animated: false) 
      self.delegate = UITableViewScrollCompletionDelegate(completion: completion, oldDelegate: self.delegate, targetOffset:targetOffset) 
      self.scrollToRowAtIndexPath(indexPath, atScrollPosition: scrollPosition, animated: true) 
     } 
    } 
} 

Это работает в большинстве случаев, хотя делегат TableView изменяется во время прокрутки, которые могут быть нежелательной в некоторых случаях.

Смежные вопросы