Iphone – How to use a CGBlendMode on a UIView that scrolls above a fixed background

core-graphicsiphoneuiview

Our main UIView is a UIScrollView with a fixed background image (very common, obviously). In that scrollView, we have several UIViews that hold content and scroll up and down as the user scrolls (also common). Those UIViews each have their own background, a simple gradient from white to black.

The goal is to have the background gradient of those (inner) UIViews be partially opaque AND use a CGBlendMode other than "kCGBlendModeNormal" (specifically, "kCGBlendModeOverlay"). You should be able to see through to the "parent" scrollView’s fixed background image as the UIViews scroll up and down above it.

- (void)drawRect:(CGRect)rect {
    gradientStart = [UIColor colorWithRed:1 green:1 blue:1 alpha:1.0];
    gradientEnd = [UIColor colorWithRed:0 green:0 blue:0 alpha:1.0];

    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
    CGFloat locations[2] = { 0.0f, 1.0f };
    NSArray *colors = [NSArray arrayWithObjects:(id)gradientStart.CGColor, (id)gradientEnd.CGColor, nil];

    CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef)colors, locations);
    CGColorSpaceRelease(colorSpace);

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetAlpha(context, 0.50); //this works!
    CGContextSetBlendMode(context, kCGBlendModeOverlay); //doesn’t seem to do anything!

    CGContextClearRect(context, rect);

    CGPoint startPoint, endPoint;
    startPoint.x = 0.0;
    startPoint.y = 0.0;
    endPoint.x = 0.0;
    endPoint.y = rect.size.height;

    CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, 0);

    CGGradientRelease(gradient);

    [super drawRect:rect];
}

Everything works as expected except the CGContextSetBlendMode, which is ignored. We can't seem to find a way to change the blendMode of a UIView relative to what is behind it, the same way you can with alpha. Please note that this is different than building up multiple layers in a SINGLE UIView; in that case, this technique does change the blendMode of the layers "on top". We want to see through to the parent scrollView's fixed background image (as we scroll the child view up and down above it), with both an alpha and an overlay blend applied.

Here's an image showing the issue: http://img2.sbck.us/blendmode.png

Thanks in advance for your help!

Best Answer

I believe what you want is not possible with your current setup. On iOS, it is simply not possible for the blend mode of a view to have an effect on the stuff that is drawn under the view. You would have to draw the scroll view's background and the gradients in the same view.

Related Topic