在NSCollectionView + NSScrollView中的鼠标悬停

时间:2013-07-18 18:30:51

标签: objective-c macos appkit nsscrollview nstrackingarea

在10.7+项目中,当鼠标位于集合视图项的视图范围内时,我试图在NSCollectionViewItem中启用UI元素。对于填充NSCollectionView的每个集合视图项,我有一个自定义视图,使用其边界创建单独的NSTrackingArea:

- (void) initializeMouseTracking
{
    self.trackingArea = [[NSTrackingArea alloc] initWithRect:[self bounds] options:NSTrackingMouseEnteredAndExited|NSTrackingActiveAlways owner:self userInfo:nil];
    [self addTrackingArea:self.trackingArea];

    NSPoint mouseLocation = [[self window] mouseLocationOutsideOfEventStream];
    mouseLocation = [self convertPoint: mouseLocation fromView: nil];

    if (NSPointInRect(mouseLocation, [self bounds]) == YES)
    {
        [self mouseEntered:nil];
    }
    else
    {
        [self mouseExited:nil];
    }
}

跟踪区域工作得很好,直到滚动NSCollectionView内容。很明显,在滚动期间和之后需要重置跟踪区域。 我试图通过几种方式使NSTrackingAreas无效并重新创建:

- (void) resetMouseTracking
{
    [self removeTrackingArea:self.trackingArea];
    [self initializeMouseTracking];
}


- (void) scrollWheel:(NSEvent *)theEvent
{
    [self resetMouseTracking];
    [super scrollWheel:theEvent];
}


- (void) viewDidMoveToWindow:(NSWindow *)newWindow
{   
    [self resetMouseTracking];
    [super viewWillMoveToWindow:newWindow];
}


- (void) updateTrackingAreas
{
    [self resetMouseTracking];
    [super updateTrackingAreas];
}

但不仅这些尝试有不完整和错误的结果,在滚动(ala scrollwheel :)期间不断重新计算跟踪区域似乎是不必要的。相反,有一种有效的方法可以捕获滚动事件的开始和偏移(在iOS中很容易),这样我可以在滚动期间使所有跟踪区域无效。在scrollview的contentView上使用NSViewBoundsDidChangeNotification告诉我滚动正在发生,但它并不表示它何时开始或停止。

从NSScrollView获取滚动开始和结束通知是否需要深入子类化或是否还有其他我忽略的内容?它有一种完全不同的方法,显示出更多的希望吗?

2 个答案:

答案 0 :(得分:0)

在Cocoa中滚动视图,与iOS不同,所有内容都在documentView上完成(而不是contentView)。 您可能需要[scrollView documentVisibleRect].origin作为内容偏移量。

查看此answer以获取更多类似的UIScrollView和NSScrollView比较

答案 1 :(得分:-1)

一种不同的方法...... NSView继承自NSResponder类。 NSResponder有方法“mouseEntered:”和“mouseExited:”。我的建议是尽可能使用NSView子类中的那些并跳过跟踪区域。