ios 以编程方式设置 contentOffset 触发 scrollViewDidScroll
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9418311/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Setting contentOffset programmatically triggers scrollViewDidScroll
提问by DBD
I've got a a few UIScrollView
on a page. You can scroll them independently or lock them together and scroll them as one. The problem occurs when they are locked.
我UIScrollView
在一页上有一些。您可以单独滚动它们或将它们锁定在一起并将它们作为一个滚动。当它们被锁定时就会出现问题。
I use UIScrollViewDelegate
and scrollViewDidScroll:
to track movement. I query the contentOffset
of the UIScrollView
which changed and then reflect change to other scroll views by setting their contentOffset
property to match.
我使用UIScrollViewDelegate
和scrollViewDidScroll:
来跟踪运动。我查询contentOffset
的UIScrollView
哪些改变,然后反映他们的设置更改为其他滚动视图contentOffset
属性相匹配。
Great.... except I noticed a lot of extra calls. Programmatically changing the contentOffset
of my scroll views triggers the delegate method scrollViewDidScroll:
to be called. I've tried using setContentOffset:animated:
instead, but I'm still getting the trigger on the delegate.
太好了......除了我注意到很多额外的电话。以编程方式更改contentOffset
滚动视图的 会触发scrollViewDidScroll:
调用委托方法。我试过使用setContentOffset:animated:
,但我仍然在委托上触发。
How can I modify my contentOffsets programmatically to not trigger scrollViewDidScroll:
?
如何以编程方式修改我的 contentOffsets 以不触发scrollViewDidScroll:
?
Implementation notes....
Each UIScrollView
is part of a custom UIView
which uses delegate pattern to call back to the presenting UIViewController
subclass that handles coordinating the various contentOffset
values.
实现说明......每个UIScrollView
都是自定义的一部分,UIView
它使用委托模式回调UIViewController
处理协调各种contentOffset
值的呈现子类。
回答by Tark
It is possible to change the content offset of a UIScrollView
without triggering the delegate callback scrollViewDidScroll:
, by setting the bounds of the UIScrollView
with the origin set to the desired content offset.
可以在UIScrollView
不触发委托回调的情况下更改 a 的内容偏移量,方法是将原点scrollViewDidScroll:
的边界UIScrollView
设置为所需的内容偏移量。
CGRect scrollBounds = scrollView.bounds;
scrollBounds.origin = desiredContentOffset;
scrollView.bounds = scrollBounds;
回答by Abhijit
Try
尝试
id scrollDelegate = scrollView.delegate;
scrollView.delegate = nil;
scrollView.contentOffset = point;
scrollView.delegate = scrollDelegate;
Worked for me.
为我工作。
回答by Kukosk
What about using existing properties of UIScrollView?
使用 UIScrollView 的现有属性怎么样?
if(scrollView.isTracking || scrollView.isDragging || scrollView.isDecelerating) {
//your code
}
回答by SimplGy
Simplifying @Tark's answer, you can position the scrollview without firing scrollViewDidScroll
in one line like this:
简化@Tark 的回答,您可以scrollViewDidScroll
像这样在一行中定位滚动视图而不触发:
scrollView.bounds.origin = CGPoint(x:0, y:100); // whatever values you'd like
回答by Jake MacMullin
Another approach is to add some logic in your scrollViewDidScroll delegate to determine whether or not the change in content offset was triggered programatically or by the user's touch.
另一种方法是在您的 scrollViewDidScroll 委托中添加一些逻辑,以确定内容偏移量的更改是通过编程方式触发还是由用户触摸触发。
- Add an 'isManualScroll' boolean variable to your class.
- Set its initial value to false.
- In scrollViewWillBeginDragging set it to true.
- In your scrollViewDidScroll check to see that is it true and only respond if it is.
- In scrollViewDidEndDecelerating set it to false.
- In scrollViewWillEndDragging add logic to set it to false if the velocity is 0 (as scrollViewDidEndDecelerating won't be called in this case).
- 向您的类添加一个“isManualScroll”布尔变量。
- 将其初始值设置为 false。
- 在 scrollViewWillBeginDragging 中将其设置为 true。
- 在您的 scrollViewDidScroll 检查它是真的,只有在它是时才响应。
- 在 scrollViewDidEndDecelerating 中将其设置为 false。
- 如果速度为 0,则在 scrollViewWillEndDragging 添加逻辑以将其设置为 false(因为在这种情况下不会调用 scrollViewDidEndDecelerating)。
回答by David H
This is not a direct answer to the question, but if you are getting what appear to be spurious such messages, it can ALSO be because you are changing the bounds. I am using some Apple sample code with a "tilePages" method that removes and adds subview to a scrollview. This infrequently results in additional scrollViewDidScroll: messages called immediately, so you get into a recursion which you for sure didn't expect. In my case I got a nasty impossible to find crash.
这不是问题的直接答案,但如果您收到此类消息似乎是虚假的,也可能是因为您正在更改边界。我正在使用一些带有“tilePages”方法的 Apple 示例代码,该方法删除子视图并将子视图添加到滚动视图。这很少会导致立即调用额外的 scrollViewDidScroll: 消息,因此您会进入一个您肯定没有预料到的递归。就我而言,我遇到了一个令人讨厌的不可能找到的崩溃。
What I ended up doing was queuing the call on the main queue:
我最终做的是在主队列上排队呼叫:
- (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]; });
}
}