Щелкните NSView
У меня есть NSView
, содержащий несколько подзонов. Одно из этих представлений является прозрачным и многослойным сверху.
Мне нужно иметь возможность щелкнуть этот вид вниз до подзаголовков ниже (так, чтобы вид ниже получил статус первого ответчика), но все события мыши застревают в верхнем виде (альфа 1
, потому что я нарисуйте материал в нем - так что он должен только щелкать прозрачными областями).
Я действительно ожидал, что это сработает, так как обычно это происходит. Что не так?
Ответы
Ответ 1
Вот еще один подход. Это не требует создания нового оконного объекта и проще (и, вероятно, немного более эффективно), чем метод findNextSiblingBelowEventLocation: выше.
- (NSView *)hitTest:(NSPoint)aPoint
{
// pass-through events that don't hit one of the visible subviews
for (NSView *subView in [self subviews]) {
if (![subView isHidden] && [subView hitTest:aPoint])
return subView;
}
return nil;
}
Ответ 2
Я обошел проблему с этим фрагментом кода.
- (NSView *)findNextSiblingBelowEventLocation:(NSEvent *)theEvent {
// Translate the event location to view coordinates
NSPoint location = [theEvent locationInWindow];
NSPoint convertedLocation = [self convertPointFromBase:location];
// Find next view below self
NSArray *siblings = [[self superview] subviews];
NSView *viewBelow = nil;
for (NSView *view in siblings) {
if (view != self) {
NSView *hitView = [view hitTest:convertedLocation];
if (hitView != nil) {
viewBelow = hitView;
}
}
}
return viewBelow;
}
- (void)mouseDown:(NSEvent *)theEvent {
NSView *viewBelow = [self findNextSiblingBelowEventLocation:theEvent];
if (viewBelow) {
[[self window] makeFirstResponder:viewBelow];
}
[super mouseDown:theEvent];
}
Ответ 3
Поместите свой прозрачный вид в собственное дочернее окно.
Ответ 4
Вот версия figelwump от Swift 5:
public override func hitTest(_ point: NSPoint) -> NSView? {
// pass-through events that don't hit one of the visible subviews
return subviews.first { subview in
!subview.isHidden && nil != subview.hitTest(point)
}
}
Ответ 5
Вот версия Erik Aigner от Swift 5:
public override func mouseDown(with event: NSEvent) {
// Translate the event location to view coordinates
let convertedLocation = self.convertFromBacking(event.locationInWindow)
if let viewBelow = self
.superview?
.subviews // Find next view below self
.lazy
.compactMap({ $0.hitTest(convertedLocation) })
.first
{
self.window?.makeFirstResponder(viewBelow)
}
super.mouseDown(with: event)
}