NSScrubber 平移动画结束通知

NSScrubber pan animation end notification

特定于触摸栏的 NSScrubber 控件会在平移手势上以惯性滚动。我想收到此动画结束的通知以执行某些功能。

尝试 1

NSScrubberDelegate 有一个我实现的 - didFinishInteractingWithScrubber: 方法。但是,在我停止直接操作滑动条后不久——将手指从触摸栏上移开——我收到回调,但由于惯性,滚动继续发生。最后选择的项目不是回调此委托方法时的项目。

尝试 2

进一步挖掘,我遇到了 NSAnimation。虽然没有清楚地记录下来,但我收集到 scrubber 也是一个 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;随着洗涤器滚动,我不断接到这些电话,当滚动停止时,电话停止。这感觉最接近我想要的,但我不知道为什么在动画结束时会有这么多调用而不是只有一个。

由于 NSScrubberNSViewNSScrollView 没有暴露,我不确定我是否正在查询正确的对象以到达正确的位置 NSAnimation.

尝试 3

我也尝试过在操作结束代码上执行此操作的 hacky 路线,但没有成功

-(void)didFinishInteractingWithScrubber:(NSScrubber *)scrubber {
    NSLog(@"Manipulation ended\n");
    NSAnimationContext*c = NSAnimationContext.currentContext;
    [c setCompletionHandler:^{
        NSLog(@"Inertial scrolling stopped!\n");
    }];
}

几乎立即调用完成处理程序, 惯性滚动停止之前:(

询问

有没有办法知道滑块的平移手势惯性动画何时结束?

终于找到了注册平移手势惯性滚动动画结束回调的方法

与任何其他滚动视图一样,它也有 NSScrollViewDidEndLiveScrollNotification。使用通知中心注册回调!

NSScrollView *sv = myScrubber.enclosingScrollView;
// 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 展示这种方法。