触摸栏特定的NSScrubber
控件在平移手势上滚动惯性。我想通知这个动画结束执行一些功能。
NSScrubberDelegate
有一个我实施的- didFinishInteractingWithScrubber:
方法。然而,在我停止直接操作洗涤器后不久 - 将手指从触摸杆上抬起 - 我得到一个回调,但滚动因惯性而继续发生。选择的最终项目不是调用此委托方法时的项目。
进一步挖掘,我遇到了NSAnimation
。虽然没有清楚地记录,但我认为,洗涤器也是一个NSAnimatablePropertyContainer
,因为它的selectedIndex
属性文档说人们可以通过动画师代理动画选择:scrubber.animator.selectedIndex = i
。通过这种优点,假设平滑平移的动画属性是boundsOrigin
,我尝试查询它。
这样做我能得到一个CAAnimation
CAAnimation* a = [NSScrubber defaultAnimationForKey:@"boundsOrigin"];
// returns the same pointer value as above
// a = [myScrubber animationForKey:@"boundsOrigin"];
a.delegate = self;
...
- (void)animationDidStop:(CAAnimation *)anim
finished:(BOOL)flag {
if (flag == YES)
NSLog(@"Animation ended!\n");
}
我得到a
的有效指针值。然而,我收到了很多关于animationDidStop
的电话,所有人都有flag = YES
;当擦洗器滚动时,我不停地接收这些呼叫,当滚动停止时,呼叫停止。这感觉最接近我想要的但是我不知道为什么在动画结束时会有这么多来电而不是一个。
由于NSScrubber
的NSView
或NSScrollView
没有暴露,我不确定我是否正在查询正确的物体到达正确的NSAnimation
。
我也尝试了在操作结束代码上徒劳无功的hacky路线
-(void)didFinishInteractingWithScrubber:(NSScrubber *)scrubber {
NSLog(@"Manipulation ended\n");
NSAnimationContext*c = NSAnimationContext.currentContext;
[c setCompletionHandler:^{
NSLog(@"Inertial scrolling stopped!\n");
}];
}
在惯性滚动停止之前几乎立即调用完成处理程序:(
无论如何要知道洗涤器的平移手势惯性动画何时结束?
我终于找到了一种为pan手势的惯性滚动动画结束注册回调的方法。首先,我们要在洗涤器内部获得滚动视图:
- (NSScrollView*) getScrollViewForScrubber:(NSScrubber*) scrubber {
NSScrollView* sv = nil;
for (NSView* v in scrubber.subviews) {
if ([v isKindOfClass:[NSScrollView class]])
sv = (NSScrollView*) v;
break;
}
return sv;
}
现在,像任何其他滚动视图一样,这也有NSScrollViewDidEndLiveScrollNotification。使用通知中心注册回拨!
NSScrollView *sv = [self getScrollViewForScrubber:myScrubber];
// register for NSScrollViewWillStartLiveScrollNotification if start is also needed
[[NSNotificationCenter defaultCenter] addObserverForName:NSScrollViewDidEndLiveScrollNotification
object:sv
queue:nil
usingBlock:^(NSNotification * _Nonnull note) {
NSLog(@"Scroll complete");
}];
感谢this answer展示这种方法。