UITableView scrollViewDidScroll在动画期间被触发

5

大多数人在处理这个特定事件时遇到的问题是当有动画发生时,scrollViewDidScroll会被触发。而我的情况恰恰相反,我认为在我的情况下不应该触发scrollViewDidScroll

让我进一步解释。

我正在scrollViewDidScroll中进行动画处理,这一直很完美,直到我将UITableView移到UIView类中。

- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
   // Animation code here.
   NSLog(@"scrollViewDidScroll");
}

- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
   NSLog(@"scrollViewDidEndDecelerating");
   NSArray *indexPaths = [_myTableView indexPathsForVisibleRows];
   [_myTableView scrollToRowAtIndexPath:[indexPaths objectAtIndex:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
}

这提供了一种平滑滚动的体验,并可以自动回弹到之前的表格行。控制台可以验证scrollViewDidScroll事件是由于scrollToRowAtIndexPath而触发的。
控制台输出:
2014-03-31 22:21:43.346 Project[45843:a0b] scrollViewDidScroll
2014-03-31 22:21:43.379 Project[45843:a0b] scrollViewDidScroll
2014-03-31 22:21:43.429 Project[45843:a0b] scrollViewDidScroll
2014-03-31 22:21:43.462 Project[45843:a0b] scrollViewDidScroll
2014-03-31 22:21:43.479 Project[45843:a0b] scrollViewDidEndDecelerating
2014-03-31 22:21:43.496 Project[45843:a0b] scrollViewDidScroll
2014-03-31 22:21:43.513 Project[45843:a0b] scrollViewDidScroll
2014-03-31 22:21:43.529 Project[45843:a0b] scrollViewDidScroll

以下是需要翻译的内容:

1. 如何确保事件scrollViewDidScroll只由用户交互触发,而不是由代码自动化触发?

2. 是否有另一种方法可以提供与scrollToRowAtIndexPath相同的功能,但不会触发scrollViewDidScroll

问题如下:

1. 如何确保scrollViewDidScroll事件只由用户交互触发,而不是由代码自动化触发?

2. 是否有其他方法提供与scrollToRowAtIndexPath相同的功能,但不会触发scrollViewDidScroll


1
据我所知,如果没有调用委托方法,你是无法滚动的。你可以通过编程方式滚动来设置一个标志,并在委托方法中使用它。如果你正在以编程方式滚动,请重置该标志。希望这能帮到你。 - Rajath Shetty K
2个回答

15

我知道这是一个非常古老的问题。我只是遇到了一个类似的情况,需要在用户滚动时运行一些代码,但不在调用 scrollToRowAtIndexPath 时运行。使用scrollView 变量 draggingdecelerating,我发现了一个更简单的解决方案。

这里有三种滚动情况:

  1. 用户正在拖动
  2. 用户刚结束拖动,tableview 正在减速
  3. 通过编程方式调用 scrollForRowAtIndexPath:

以上所有情况都会触发 scrollViewDidScroll:,但是

  1. 用户正在拖动时,draggingTruedeceleratingFalse
  2. 用户刚结束拖动,tableview 正在减速时,draggingFalsedeceleratingTrue
  3. 通过编程方式调用 scrollForRowAtIndexPath: 时,draggingFalsedeceleratingFalse

因此,您的代码将类似于以下内容:

- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView.dragging)
     {
       // Do what you want when user is dragging
     } else if (scrollView.decelerating) 
     {
       // Do what you want when table is decelerating after finished dragging
     } else 
     {
       // Do what you want when table is scrolling programmatically.
     }
}

或者,如果您只想以编程方式区分滚动

- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
    if (scrollView.dragging || scrollView.decelerating)
     {
       // Scrolling by the user
     } else 
     {
       // Scrolling by the code
     }
}

2
这是一个比我自己编写的更优雅的解决方案!将其更改为被接受的答案。 - Levi Roberts

1
不久之后我发布了这个问题,休息了一会儿,回来解决了这个问题。早些时候应该这样做,而不是浪费几个小时。呃!
解决方案很简单,设置一个布尔标志,在任何编程滚动之前设置它,然后在动画完成后使用事件scrollViewDidEndScrollingAnimation更改它。
bool performingAutomatedScroll = false;

- (void) scrollViewDidScroll:(UIScrollView *)scrollView {

  // If we are scrolling because of code, don't use any animations.
  if (performingAutomatedScroll) return;

  // Animation code here.
}

- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView {

  performingAutomatedScroll = true;
  NSArray *indexPaths = [_myTableView indexPathsForVisibleRows];
  [_myTableView scrollToRowAtIndexPath:[indexPaths objectAtIndex:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
  [_myTableView reloadRowsAtIndexPaths:[_timeCarousel indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationNone];

}

- (void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {

  if (!decelerate) {
    performingAutomatedScroll = true;
    NSArray *indexPaths = [_myTableView indexPathsForVisibleRows];
    [_myTableView scrollToRowAtIndexPath:[indexPaths objectAtIndex:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];
    [_myTableView reloadRowsAtIndexPaths:[_timeCarousel indexPathsForVisibleRows] withRowAnimation:UITableViewRowAnimationNone];
  }

}

-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
  performingAutomatedScroll = false;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接