Question

I know similar question(s) have been asked before, but most answers say create a new detail disclosure button image with the required color (e.g. How to change color of detail disclosure button for table cell).

I want to be able to change it to any color I choose, dynamically, at run-time, so using a pre-configured image is not viable.

From reading around, I think there may be a few ways to do this, but I'm not sure which is the best, or exactly how to do it:

  1. Draw the required color circle in code and overlay with an image of shadow round outside of circle and arrow right (with clear alpha channel for rest, so drawn color circle is still visible)

  2. Add image of shadow round outside of circle in UIImageView, and using as a mask, flood fill within this shadow circle, then overlay the arrow.

  3. Add greyscale image, mask it with itself, and overlay the required color (e.g. http://coffeeshopped.com/2010/09/iphone-how-to-dynamically-color-a-uiimage), then overlay that with arrow image.

What is the best way, and does anyone have any code showing exactly how to do it ?

Was it helpful?

Solution

I use the following helper method to tint a grayscale image. It takes the grayscale image, the tint color, and an option mask image used to ensure the tint only happens in part of the grayscale image. This method also ensure the new image has the same (if any) resizable insets as the original image.

+ (UIImage *)tintImage:(UIImage *)baseImage withColor:(UIColor *)color mask:(UIImage *)maskImage {
    UIGraphicsBeginImageContextWithOptions(baseImage.size, NO, baseImage.scale);

    CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGRect area = CGRectMake(0, 0, baseImage.size.width, baseImage.size.height);

    CGContextScaleCTM(ctx, 1, -1);
    CGContextTranslateCTM(ctx, 0, -area.size.height);

    CGContextSaveGState(ctx);
    if (maskImage) {
        CGContextClipToMask(ctx, area, maskImage.CGImage);
    } else {
        CGContextClipToMask(ctx, area, baseImage.CGImage);
    }

    [color set];
    CGContextFillRect(ctx, area);
    CGContextRestoreGState(ctx);

    CGContextSetBlendMode(ctx, kCGBlendModeOverlay);

    CGContextDrawImage(ctx, area, baseImage.CGImage);

    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();

    UIGraphicsEndImageContext();

    if (!UIEdgeInsetsEqualToEdgeInsets(baseImage.capInsets, UIEdgeInsetsZero)) {
        newImage = [newImage resizableImageWithCapInsets:baseImage.capInsets];
    }

    return newImage;
}

Here is the non-retina grayscale detail disclosure image: enter image description here

Here is the retina version: enter image description here

Here is the non-retina mask (between the quotes - it's mostly white): "enter image description here"

And the retina mask (between the quotes: "enter image description here"

OTHER TIPS

Consider also using an icon font in a label instead of an image. Something like glyphicons. Then you can set the text colour to whatever you want. You also have good options for scaling. The cost is that you don't have quite such precise control in some cases but it should work well for your case.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top