Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ios unread message icon

Tags:

ios

iphone

I was wondering if there is a standard method in iOS to produce the numbered bubble icon for unread messages as the ones used in mail for iphone and mac.

I'm not talking about the red dots on the application item which is done with badgevalue but about the blue bubble beside the mailboxes.

Of course one can do it manually using coregraphics but it's harder to match the dimensions and color of the standard ones used in mail etc.

like image 701
Jacopo Avatar asked May 01 '11 00:05

Jacopo


2 Answers

here are three ways to do this, in order of difficulty..

  1. screen shot your mail app from your iphone, send the image into photoshop, extract the blue dot and use it as an image in your app. To use it in a tableviewcell, you just set the imageView.image = [UIImage imageName:@"blueDot.png"];

  2. same as #1, except save the image as a grayscale, this way you can use Quartz and overlay your own colors on top of it. so you can make that dot any color you want. Very cool stuff.

  3. Use Quartz to draw the whole thing. Its really not that hard. Let me know if you would like some code for that.

OK, twist my arm... here is the code to draw your own gradient sphere... from quartz.

Make a class that inherits from UIView. add the following code

static float RADIANS_PER_DEGREE=0.0174532925;

-(void) drawInContext:(CGContextRef) context
{

    // Drawing code
    CGFloat radius = self.frame.size.width/2;
    CGFloat start = 0 * RADIANS_PER_DEGREE;
    CGFloat end = 360 * RADIANS_PER_DEGREE;

    CGPoint startPoint = CGPointMake(0, 0);
    CGPoint endPoint = CGPointMake(0, self.bounds.size.height);


    //define our grayscale gradient.. we will add color later
    CGFloat cc[] =
    {
        .70,.7,.7,1,  //r,g,b,a of color1, as a percentage of full on.
        .4,.4,.4,1,  //r,g,b,a of color2, as a percentage of full on.
    };


    //set up our gradient
    CGGradientRef gradient;
    CGColorSpaceRef rgb = CGColorSpaceCreateDeviceRGB();
    gradient = CGGradientCreateWithColorComponents(rgb, cc, NULL, sizeof(cc)/(sizeof(cc[0])*4));
    CGColorSpaceRelease(rgb);


    //draw the gray gradient on the sphere


    CGContextSaveGState(context);
    CGContextBeginPath(context);
    CGContextAddArc(context, self.bounds.size.width/2, self.bounds.size.height/2, radius,start,end , 0);
    CGContextClosePath(context);
    CGContextClip(context);

    CGContextAddRect(context, self.bounds);
    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation);
    CGGradientRelease(gradient);    

    //now add our primary color.  you could refactor this to draw this from a color property
    UIColor *color = [UIColor blueColor];
    [color setFill];
    CGContextSetBlendMode(context, kCGBlendModeColor);  // play with the blend mode for difference looks
    CGContextAddRect(context, self.bounds);  //just add a rect as we are clipped to a sphere
    CGContextFillPath(context);


    CGContextRestoreGState(context);


}


- (void)drawRect:(CGRect)rect
{
    CGContextRef context = UIGraphicsGetCurrentContext();

    [self drawInContext:context];
}
like image 72
Jason Cragun Avatar answered Oct 19 '22 22:10

Jason Cragun


If you want to use a graphic resource from iOS, you can find it using the UIKit-Artwork-Extractor tool. Extract everything to the desktop and find the one you want. For example, the red badge for notifications is called SBBadgeBG.png. I don't know which one you mean, so search for it yourself :P

This is what I did to use a badge, the procedure is exactly the same to show a bubble in a subview of your table:

// Badge is an image with 14+1+14 pixels width and 15+1+15 pixels height.
// Setting the caps to 14 and 15 preserves the original size of the sides, so only the pixel in the middle is stretched.
UIImage *image = [UIImage imageNamed:@"badge"];
self.badgeImage = [image stretchableImageWithLeftCapWidth:(image.size.width-1)/2 topCapHeight:(image.size.height-1)/2];

// what size do we need to show 3 digits using the given font?
self.badgeFont = [UIFont fontWithName:@"Helvetica-Bold" size:13.0];
CGSize maxStringSize = [[NSString stringWithString:@"999"] sizeWithFont:self.badgeFont];

// set the annotation frame to the max needed size
self.frame = CGRectMake(0,0, 
                        self.badgeImage.size.width + maxStringSize.width, 
                        self.badgeImage.size.height + maxStringSize.height);

and then override the method drawRect: of your view to paint the badge and the numbers inside:

- (void)drawRect:(CGRect)rect {

    // get the string to show and calculate its size
    NSString *string = [NSString stringWithFormat:@"%d",self.badgeNumber];
    CGSize stringSize = [string sizeWithFont:self.badgeFont];

    // paint the image after stretching it enough to acommodate the string 
    CGSize stretchedSize = CGSizeMake(self.badgeImage.size.width + stringSize.width, 
                                      self.badgeImage.size.height);

    // -20% lets the text go into the arc of the bubble. There is a weird visual effect without abs.
    stretchedSize.width -= abs(stretchedSize.width *.20);

    [self.badgeImage drawInRect:CGRectMake(0, 0, 
                                           stretchedSize.width, 
                                           stretchedSize.height)];
    // color of unread messages
    [[UIColor yellowColor] set];

    // x is the center of the image minus half the width of the string.
    // Same thing for y, but 3 pixels less because the image is a bubble plus a 6px shadow underneath.
    float height = stretchedSize.height/2 - stringSize.height/2 - 3;
    height -= abs(height*.1);
    CGRect stringRect = CGRectMake(stretchedSize.width/2 - stringSize.width/2,
                                   height,
                                   stringSize.width, 
                                   stringSize.height);
    [string drawInRect:stringRect withFont:badgeFont];
}
like image 42
Jano Avatar answered Oct 19 '22 23:10

Jano