views:

347

answers:

2

I would like to write a UIView subclass that, among other things, colors whatever's underneath it a certain color. This is what I've come up with, but it unfortunately doesn't seem to work correctly:

#import <UIKit/UIKit.h>

@class MyOtherView;
@interface MyView : UIView
{
    MyOtherView *subview;
}
@end

@implementation MyView

- (id)initWithFrame:(CGRect)frame
{
    if (self = [super initWithFrame:frame]) {
     frame.origin.x += 100.0;
     frame.origin.y += 100.0;
     frame.size.width = frame.size.height = 200.0;
     subview = [[MyOtherView alloc] initWithFrame:frame];
     [self addSubview:subview];
     [subview release];
    }
    return self;
}

- (void)drawRect:(CGRect)rect
{
    // Draw a background to test out on
    UIImage *image = [UIImage imageNamed:@"somepic.png"];
    [image drawAtPoint:rect.origin];

    const CGContextRef ctx = UIGraphicsGetCurrentContext();
    [[UIColor blueColor] setFill];
    rect.size.width = rect.size.height = 200.0;
    CGContextFillRect(ctx, rect);
}

@end

@interface MyOtherView : UIView
@end

@implementation MyOtherView

- (void)drawRect:(CGRect)rect
{
    // This should tint "MyView" but it doesn't.
    const CGContextRef ctx = UIGraphicsGetCurrentContext();
    CGContextSaveGState(ctx);
    CGContextSetBlendMode(ctx, kCGBlendModeScreen);
    [[UIColor redColor] setFill];
    CGContextFillRect(ctx, rect);
    CGContextRestoreGState(ctx);
}

@end

I want "MyOtherView" to color "MyView" red where it overlaps, but instead it just draws an opaque red block onto it. However, this seems work fine if I copy the -drawRect: function from "MyOtherView" and append it to the one in "MyView" (this took me quite a headache to finally realize). Anyone know what I'm doing wrong? Is it even possible to do this, or should I be approaching it differently?

A: 

I think you're over-thinking this. Overlay one view over the other, and set the alpha of the top view to 0.5. You will also need to set opaque to NO.

If you set the background color of the view appropriately, you won't even need to override drawRect.

Mark Bessey
I've tried setting the alpha, but unfortunately I can't get the correct color that way, not to mention any of Quartz' fancy blend effects.Sorry, I realize I could just use the background color here, I was just using it as a simple example of tinting another view. In my app it's a bit more complicated than that.
Michael
I don't think you can adjust the blending mode for a particular view. Maybe you could use multiple CALayers within one view?
Mark Bessey
A: 

Might want to check out this SO question.

Ramin
This is close to what I want, only everything's done in the same -drawRect: function. How do I do this with separate views?
Michael
In that question they were looking for a single color for the whole screen, but that's because they had only one imageview on the screen. Just apply the same technique to each derived view you want colored. Every subclassed view gets its own drawRect method and tint value. It can also be generically applied to UIViews instead of UIImageViews so you should be able to apply it to non-image graphics as well.
Ramin