在构建自定义NSButton
时,我遇到了处理突出显示行为的问题。单击按钮,按住并将光标拖动到按钮边界之外,不会传递mouseExited:
和mouseEntered:
个事件。我理解原因,因为mouseDown:
调用[super mouseDown:event];
将阻止点击发布。
在研究这个问题时,我遇到了this Stack Overflow post,它描述了同样的问题。提到的解决方案是将NSTrackingEnabledDuringMouseDrag
添加到我已完成的NSTrackingArea
选项中,但我仍然会看到此问题。我尝试了另一个提出的解决方案,在循环中处理下一个事件,但这导致奇怪的行为。按钮文本颜色在鼠标按下时变黑,而不是突出显示变暗的颜色,并且在释放鼠标时它不会不亮,它仍然是黑色。
我正在使用Xcode 9.3,在macOS 10.13.4上运行。
这是我的NSButton
子类:
@interface BorderlessButton : NSButton {
NSColor *_tempColor;
}
@property (strong, nonatomic) NSColor *color;
@end
@interface BorderlessButton ()
@property (nonatomic) BOOL pressed;
@end
@implementation BorderlessButton
- (id)init {
if (self = [super init]) {
[self setUp];
}
return self;
}
- (id)initWithFrame:(NSRect)frameRect {
if (self = [super initWithFrame:frameRect]) {
[self setUp];
}
return self;
}
- (id)initWithCoder:(NSCoder *)aDecoder {
if (self = [super initWithCoder:aDecoder]) {
[self setUp];
}
return self;
}
- (void)setUp {
_color = [NSColor redColor];
[self setTitle:self.title];
[self setButtonType:NSButtonTypeMomentaryChange];
[self setBordered:NO];
NSTrackingArea *area = [[NSTrackingArea alloc] initWithRect:self.bounds
options:NSTrackingMouseEnteredAndExited | NSTrackingActiveAlways | NSTrackingEnabledDuringMouseDrag
owner:self
userInfo:nil];
[self addTrackingArea:area];
}
- (void)setTitle:(NSString *)title {
[super setTitle:title];
NSMutableAttributedString *colorTitle = [[NSMutableAttributedString alloc] initWithAttributedString:[self attributedTitle]];
[colorTitle addAttributes:@{NSFontAttributeName: self.font, NSForegroundColorAttributeName: self.color} range:NSMakeRange(0, [colorTitle length])];
[self setAttributedTitle:colorTitle];
}
- (void)setColor:(NSColor *)color {
_color = color;
[self setTitle:self.title];
}
- (void)mouseDown:(NSEvent *)event {
self.pressed = YES;
[self highlight:YES];
[super mouseDown:event]; // this blocks until released
[self mouseUp:event];
}
- (void)mouseUp:(NSEvent *)event {
self.pressed = NO;
[self highlight:NO];
[super mouseUp:event];
}
//FIXME: Not called after mouse press down and hold then exit
- (void)mouseExited:(NSEvent *)event {
if (self.pressed) {
[self highlight:NO];
}
[super mouseExited:event];
}
- (void)mouseEntered:(NSEvent *)event {
if (self.pressed) {
[self highlight:YES];
}
[super mouseEntered:event];
}
- (void)highlight:(BOOL)flag {
if (flag) {
if (self.isEnabled) {
NSColor *dimmedColor = [self dimmedColor];
_tempColor = _color;
self.color = dimmedColor;
[self setTitle:self.title];
}
} else {
if (self.isEnabled) {
self.color = _tempColor;
[self setTitle:self.title];
}
}
}
- (NSColor *)dimmedColor {
return [self.color colorWithAlphaComponent:0.5];
}
@end