Search code examples
objective-cmacoscocoabadgensdocktile

How to show a badge on an NSView (Mac OS X)


To add a badge to your application in the dock is easy, you just call [NSDockTile setBadgeLabel]. But I want to add a badge to a generic NSView. Is there any way to do this? Or failing that, how do you go about drawing one so that it looks consistent with the rest of the system UI?


Solution

  • There is no builtin methods to draw a badge on NSView so you should draw it by yourself. Here is my code to draw a badge:

    - (void)drawBadgeImageWithText:(NSString*)text atPoint:(NSPoint)point
    {
        NSSize badgeSize = [self badgeSizeForString:text];
        NSRect badgeRect = NSMakeRect(point.x - badgeSize.width, point.y - badgeSize.height, badgeSize.width, badgeSize.height);
    
        [NSGraphicsContext saveGraphicsState];
    
        // Set a shadow
        NSShadow* shadow = [[NSShadow alloc] init];
        shadow.shadowColor = [[NSColor blackColor] colorWithAlphaComponent:0.4];
        shadow.shadowBlurRadius = 1;
        shadow.shadowOffset = NSMakeSize(0, -1);
        [shadow set];
    
        // Draw white border
        NSBezierPath* path = [NSBezierPath bezierPathWithRoundedRect:badgeRect xRadius:badgeSize.height / 2.0 yRadius:badgeSize.height / 2.0];
        [[NSColor whiteColor] setFill];
        [path fill];
    
        [NSGraphicsContext restoreGraphicsState];
    
        // Fill the background with red gradient 
        badgeRect = NSInflateRect(badgeRect, -1.5, -1.5);
        path = [NSBezierPath bezierPathWithRoundedRect:badgeRect xRadius:badgeSize.height / 2.0 yRadius:badgeSize.height / 2.0];
        [[NSColor colorWithCalibratedRed:192.0 / 255.0 green:0.0 blue:0.0 alpha:1.0] setFill];
        [path fill];
    
        NSGradient* gradient = [[NSGradient alloc] initWithStartingColor:[NSColor colorWithCalibratedRed:241.0 / 255.0 green:113.0 / 255.0 blue:115.0 / 255.0 alpha:1.0]
                                                             endingColor:[NSColor colorWithCalibratedRed:192.0 / 255.0 green:0.0 blue:0.0 alpha:1.0]];
        [gradient drawInBezierPath:path angle:-90.0];
    
        // Draw the text
        NSMutableParagraphStyle* paragraphStyle = [[NSMutableParagraphStyle alloc] init];
        [paragraphStyle setAlignment:NSCenterTextAlignment];
    
        NSDictionary* textAttributes = @{NSForegroundColorAttributeName:[NSColor whiteColor], NSParagraphStyleAttributeName:paragraphStyle};
    
        [text drawInRect:badgeRect withAttributes:textAttributes];
    }
    
    - (NSSize)badgeSizeForString:(NSString*)string
    {
        NSDictionary* attributes = [NSDictionary dictionaryWithObject:[NSFont systemFontOfSize:13] forKey: NSFontAttributeName];
        NSSize size = [string sizeWithAttributes:attributes];
    
        // Paddings
        size.height += 2.0;
        size.width += 12.0;
    
        return size;
    }