NSScrollView检测滚动位置

时间:2014-04-17 07:33:23

标签: objective-c cocoa nstableview nsscrollview

如何在底部滚动时检测位置滚动?

[[_scrollView contentView] setPostsBoundsChangedNotifications:YES];
[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(boundsDidChangeNotification:)
                                             name:NSViewBoundsDidChangeNotification
                                           object:[_scrollView contentView]];





- (void) boundsDidChangeNotification: (NSNotification *) notification
{
    NSPoint currentScrollPosition = [[_scrollView contentView] bounds].origin;
}

4 个答案:

答案 0 :(得分:11)

<强>更新
我原来的答案是完全错误的 感谢JWWalker和Wil Shipley通过评论让我意识到这一点。

对于通过搜索来到这里的人来说,这是一个希望更有帮助的答案:
UIScrollView不同,NSScrollView不提供委托方法,以便在视图滚动到顶部/底部时通知您。
要检测这些情况,您必须启用boundsDidChange通知并订阅它们。

接收边界更新时,您可以检查剪辑视图边界的y坐标是0(=底部),还是剪辑视图边界的上边缘是否与文档对齐view(= top)。

private func configureScrollView() {
        self.scrollView.contentView.postsBoundsChangedNotifications = true
        NotificationCenter.default.addObserver(self, selector: #selector(contentViewDidChangeBounds), name: NSView.boundsDidChangeNotification, object: self.scrollView.contentView)
    }

@objc
func contentViewDidChangeBounds(_ notification: Notification) {
    guard let documentView = scrollView.documentView else { return }

    let clipView = scrollView.contentView
    if clipView.bounds.origin.y == 0 {
        print("bottom")
    } else if clipView.bounds.origin.y + clipView.bounds.height == documentView.bounds.height {
        print("top")
    }
}

对于使用弹性滚动的滚动视图,更新会有一个短暂的延迟,因为剪辑视图似乎会推迟边界更改通知,直到滚动弹跳结束。

<击> 您可以使用NSScrollView的contentView的可见矩形而不是边界:

- (void)boundsDidChangeNotification:(NSNotification*) notification
{
    NSRect visibleRect = [[_scrollView contentView] documentVisibleRect];
    NSLog(@"Visible rect:%@", NSStringFromRect(visibleRect));
    NSPoint currentScrollPosition = visibleRect.origin;
}

内容视图边界在滚动过程中不会发生变化,所以在原始代码中,bounds.origin可能总是返回0/0。

答案 1 :(得分:4)

if (_scrollView.verticalScroller.floatValue > 0.9)
{
    // bottom
    // do something
}

答案 2 :(得分:0)

如果要在滚动结束后进行检测。 @thomas的答案是在视图滚动时检测到

  NotificationCenter.default.addObserver(
                self,
                selector: #selector(scrollViewDidScroll),
                name:NSScrollView.didLiveScrollNotification,
                object: scrollView
            )



  @objc func scrollViewDidScroll (notification: NSNotification) {

        guard let documentView = scrollView.documentView else { return }

        let clipView = scrollView.contentView
        if clipView.bounds.origin.y == 0 {
            print("top")

        } else if clipView.bounds.origin.y + clipView.bounds.height == documentView.bounds.height {

            print("bottom")

}
    }

答案 3 :(得分:0)

以请求的实际语言OP:

- (void) awakeFromNib
{
    [super awakeFromNib];

    NSView* objectToTrack = self.tableView.enclosingScrollView.contentView;

    [[NSNotificationCenter defaultCenter] addObserver: self
                                             selector: @selector(didObserveScrolling:)
                                                 name: NSViewBoundsDidChangeNotification
                                               object: objectToTrack];
}

- (void) didObserveScrolling: (id) sender
{
    self.needsDisplay = YES;
    //or do whatever you need to in response for the content scrolling

}

- (void) dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver: self];
}

我在自定义视图中使用它,该视图用作NSTableView页脚以显示列平均值。