ios 如何检测 UIScrollView 何时完成滚动
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/993280/
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
How to detect when a UIScrollView has finished scrolling
提问by Michael Gaylord
UIScrollViewDelegate has got two delegate methods scrollViewDidScroll:
and scrollViewDidEndScrollingAnimation:
but neither of these tell you when scrolling has completed. scrollViewDidScroll
only notifies you that the scroll view did scroll not that it has finished scrolling.
UIScrollViewDelegate 有两个委托方法scrollViewDidScroll:
,scrollViewDidEndScrollingAnimation:
但它们都不会告诉您滚动何时完成。scrollViewDidScroll
只通知您滚动视图确实滚动而不是它已完成滚动。
The other method scrollViewDidEndScrollingAnimation
only seems to fire if you programmatically move the scroll view not if the user scrolls.
另一种方法scrollViewDidEndScrollingAnimation
似乎仅在您以编程方式移动滚动视图时才触发,而不是在用户滚动时触发。
Does anyone know of scheme to detect when a scroll view has completed scrolling?
有谁知道检测滚动视图何时完成滚动的方案?
回答by Ashley Smart
The 320 implementationsare so much better - here is a patch to get consistent start/ends of the scroll.
在320点的实现是好多了-这里是一个补丁来获得滚动一致的开始/结束。
-(void)scrollViewDidScroll:(UIScrollView *)sender
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
//ensure that the end of scroll is fired.
[self performSelector:@selector(scrollViewDidEndScrollingAnimation:) withObject:sender afterDelay:0.3];
...
}
-(void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
{
[NSObject cancelPreviousPerformRequestsWithTarget:self];
...
}
回答by Suvesh Pratapa
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
[self stoppedScrolling];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (!decelerate) {
[self stoppedScrolling];
}
}
- (void)stoppedScrolling {
// ...
}
回答by texmex5
I think scrollViewDidEndDecelerating is the one you want. Its UIScrollViewDelegates optional method:
我认为 scrollViewDidEndDecelerating 是你想要的。它的 UIScrollViewDelegates 可选方法:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
Tells the delegate that the scroll view has ended decelerating the scrolling movement.
告诉委托滚动视图已结束减速滚动移动。
回答by Aurelien Porte
For all scrolls related to dragging interactions, this will be sufficient:
对于与拖动交互相关的所有滚动,这就足够了:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
_isScrolling = NO;
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (!decelerate) {
_isScrolling = NO;
}
}
Now, if your scroll is due to a programmatic setContentOffset/scrollRectVisible (with animated
= YES or you obviously know when scroll is ended):
现在,如果您的滚动是由于程序化的 setContentOffset/scrollRectVisible(使用animated
= YES 或者您显然知道滚动何时结束):
- (void)scrollViewDidEndScrollingAnimation {
_isScrolling = NO;
}
If your scroll is due to something else (like keyboard opening or keyboard closing), it seems like you'll have to detect the event with a hack because scrollViewDidEndScrollingAnimation
is not useful either.
如果您的滚动是由于其他原因(例如键盘打开或键盘关闭),则似乎您必须使用 hack 来检测该事件,因为这scrollViewDidEndScrollingAnimation
也没有用。
The case of a PAGINATEDscroll view:
一个的情况下分页滚动视图:
Because, I guess, Apple apply an acceleration curve, scrollViewDidEndDecelerating
get called for every drag so there's no need to use scrollViewDidEndDragging
in this case.
因为,我想,Apple 应用了一条加速曲线,scrollViewDidEndDecelerating
每次拖动都会被调用,所以scrollViewDidEndDragging
在这种情况下不需要使用。
回答by Wayne
This has been described in some of the other answers, but here's (in code) how to combine scrollViewDidEndDecelerating
and scrollViewDidEndDragging:willDecelerate
to perform some operation when scrolling has finished:
这已经在其他一些答案中进行了描述,但是这里(在代码中)滚动完成后如何组合scrollViewDidEndDecelerating
和scrollViewDidEndDragging:willDecelerate
执行一些操作:
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView
{
[self stoppedScrolling];
}
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView
willDecelerate:(BOOL)decelerate
{
if (!decelerate) {
[self stoppedScrolling];
}
}
- (void)stoppedScrolling
{
// done, do whatever
}
回答by Aberrant
I only just found this question, which is pretty much the same I asked: How to know exactly when a UIScrollView's scrolling has stopped?
我刚刚发现了这个问题,这与我问的几乎相同: 如何准确知道 UIScrollView 的滚动何时停止?
Though didEndDecelerating works when scrolling, panning with stationary release does not register.
尽管 didEndDecelerating 在滚动时有效,但使用固定释放进行平移不会注册。
I eventually found a solution. didEndDragging has a parameter WillDecelerate, which is false in the stationary release situation.
我最终找到了解决方案。didEndDragging 有一个参数 WillDecelerate,在静止释放情况下为 false。
By checking for !decelerate in DidEndDragging, combined with didEndDecelerating, you get both situations that are the end of scrolling.
通过检查 DidEndDragging 中的 !decelerate 并结合 didEndDecelerating,您可以获得滚动结束的两种情况。
回答by Umair
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
scrollingFinished(scrollView: scrollView)
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if decelerate {
//didEndDecelerating will be called for sure
return
}
else {
scrollingFinished(scrollView: scrollView)
}
}
func scrollingFinished(scrollView: UIScrollView) {
// Your code
}
回答by Zappel
If you're into Rx, you can extend UIScrollView like this:
如果你喜欢 Rx,你可以像这样扩展 UIScrollView:
import RxSwift
import RxCocoa
extension Reactive where Base: UIScrollView {
public var didEndScrolling: ControlEvent<Void> {
let source = Observable
.merge([base.rx.didEndDragging.map { !scrollView.rx.didEndScrolling.subscribe(onNext: {
// Do what needs to be done here
})
},
base.rx.didEndDecelerating.mapTo(true)])
.filter { func scrollViewDidScroll(scrollView: UIScrollView) {
// example code
}
func scrollViewDidEndDragging(scrollView: UIScrollView, willDecelerate decelerate: Bool) {
// example code
}
func scrollViewDidEndZooming(scrollView: UIScrollView, withView view: UIView!, atScale scale: CGFloat) {
// example code
}
}
.mapTo(())
return ControlEvent(events: source)
}
}
which will allow you to just do like this:
这将允许您这样做:
-(void)scrollViewDidScroll:(UIScrollView *)sender
{
if(self.scrollView_Result.contentOffset.x == self.scrollView_Result.frame.size.width) {
// You have reached page 1
}
}
This will take into account both dragging and deceleration.
这将同时考虑拖动和减速。
回答by zzzz
Swift version of accepted answer:
已接受答案的 Swift 版本:
##代码##回答by Ege Akpinar
I've tried Ashley Smart's answer and it worked like a charm. Here's another idea, with using only scrollViewDidScroll
我已经尝试过 Ashley Smart 的答案,它的效果非常好。这是另一个想法,只使用 scrollViewDidScroll
##代码##I just had two pages so it worked for me. However, if you have more than one page, it could be problematic (you could check whether the current offset is a multiple of the width but then you wouldn't know if the user stopped at 2nd page or is on his way to 3rd or more)
我只有两页,所以它对我有用。但是,如果您有多个页面,则可能会出现问题(您可以检查当前偏移量是否是宽度的倍数,但您将不知道用户是停在第 2 页还是正在前往第 3 页或更多的)