65

我有UIScrollView一页上有几个。您可以单独滚动它们或将它们锁定在一起并将它们作为一个滚动。当它们被锁定时会出现问题。

我使用UIScrollViewDelegatescrollViewDidScroll:来跟踪运动。我查询其中更改contentOffsetUIScrollView,然后通过将它们的contentOffset属性设置为匹配来反映对其他滚动视图的更改。

太好了....除了我注意到很多额外的电话。以编程方式更改我的滚动视图会触发要调用contentOffset的委托方法。scrollViewDidScroll:我尝试过使用setContentOffset:animated:,但我仍然在委托上获得触发器。

如何以编程方式修改我的 contentOffsets 以不触发scrollViewDidScroll:

实现说明......每个UIScrollView都是自定义的一部分,UIView它使用委托模式回调UIViewController处理协调各种contentOffset值的呈现子类。

4

6 回答 6

111

通过将原点设置为所需内容偏移量的边界设置,可以在UIScrollView不触发委托回调的情况下更改 a 的内容偏移量。scrollViewDidScroll:UIScrollView

CGRect scrollBounds = scrollView.bounds;
scrollBounds.origin = desiredContentOffset;
scrollView.bounds = scrollBounds;
于 2012-02-23T18:05:05.487 回答
82

尝试

id scrollDelegate = scrollView.delegate;
scrollView.delegate = nil;
scrollView.contentOffset = point;
scrollView.delegate = scrollDelegate;

为我工作。

于 2013-07-25T11:10:25.113 回答
56

使用 UIScrollView 的现有属性怎么样?

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    if (scrollView.isTracking || scrollView.isDragging || scrollView.isDecelerating) {
        /// The content offset was changed programmatically.
        /// Your code goes here.
    }
}
于 2014-11-08T16:35:08.197 回答
10

另一种方法是在您的 scrollViewDidScroll 委托中添加一些逻辑,以确定内容偏移量的变化是通过编程方式触发还是由用户触摸触发。

  • 向您的类添加一个“isManualScroll”布尔变量。
  • 将其初始值设置为 false。
  • 在 scrollViewWillBeginDragging 中将其设置为 true。
  • 在您的 scrollViewDidScroll 中检查它是否为真,如果是则仅响应。
  • 在 scrollViewDidEndDecelerating 中将其设置为 false。
  • 如果速度为 0,则在 scrollViewWillEndDragging 添加逻辑以将其设置为 false(因为在这种情况下不会调用 scrollViewDidEndDecelerating)。
于 2014-09-11T01:39:33.560 回答
6

简化@Tark 的答案,您可以定位滚动视图而无需scrollViewDidScroll像这样在一行中触发:

scrollView.bounds.origin = CGPoint(x:0, y:100); // whatever values you'd like
于 2015-03-10T12:33:09.093 回答
4

这不是问题的直接答案,但如果您收到看似虚假的此类消息,也可能是因为您正在更改界限。我正在使用一些带有“tilePages”方法的Apple示例代码,该方法可以删除子视图并将其添加到滚动视图。这很少会导致立即调用额外的 scrollViewDidScroll: 消息,因此您会陷入您肯定没想到的递归。就我而言,我遇到了令人讨厌的不可能找到崩溃。

我最终做的是在主队列中排队呼叫:

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if(scrollView == yourScrollView) {
        // dispatch fixes some recursive call to scrollViewDidScroll in tilePages (related to removeFromSuperView)
        // The reason can be found here: http://stackoverflow.com/questions/9418311
        dispatch_async(dispatch_get_main_queue(), ^{ [self tilePages]; });
    }
}
于 2012-03-31T21:00:26.347 回答