Search code examples
iphoneios5calayerrender

How will work addSublayer and renderInContext in iOS


When i have written code as following way..

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

    sublayer = [CALayer layer];
    sublayer.backgroundColor = [UIColor redColor].CGColor;
    sublayer.opaque = NO;
    sublayer.frame = CGRectMake(30, 30, 250, 200);
    [sublayer renderInContext:context];

    sublayer1 = [CALayer layer];
    sublayer1.opaque = NO;
    sublayer1.backgroundColor = [UIColor greenColor].CGColor;
    sublayer1.frame = CGRectMake(120, 120, 100, 250);
    [sublayer1 renderInContext:context];

}

I got as following first image as

enter image description here enter image description here

The positions of sublayer, sublayer1 are not correct way because i have set frames to them. The intersection of them is blended color. Why are they not set the actual position?

But when i use addSublayer, i got as above second image. Here the positions of sublayer, sublayer1 are correct way. The intersection of them is not blended color. What happened like that.

Why i created sublayer is, when i drag sublayers the intersection part of them has to be blended color. Please anyone explain to me.

Thanks in Advance.


Solution

  • This is what happens in your code: In the first case, you just drew the layers in the graphics context of the view's underlying layer. That's what drawRect does. The origin of the frame doesn't affect that because it just positions sublayers inside their parent layer. But here, the layer is never added to the parent layer, so the origin does nothing at all and both shapes appear at 0, 0.

    In the second case, first the exact same thing happened as before, but because you also added the layers to the layer hierarchy, they got rendered again on top of the view's underlying layer, at the specified position. Each sublayer is rendered in it's own context, so the blend mode you set in drawRect has no effect on them.

    Actually you don't need sublayers at all if you just want to get an image of the two rectangles. You can draw them directly in drawRect in the view's underlying layer:

    - (void)drawRect:(CGRect)rect
    {
        CGContextRef ctx = UIGraphicsGetCurrentContext();
        CGContextSetBlendMode(ctx, kCGBlendModeDifference);
    
        CGContextSetFillColorWithColor(ctx, [UIColor redColor].CGColor);
        CGRect rect1 = CGRectMake(30, 30, 250, 200);
        CGContextFillRect(ctx, rect1);
    
        CGContextSetFillColorWithColor(ctx, [UIColor greenColor].CGColor);
        CGRect rect2 = CGRectMake(120, 120, 100, 250);
        CGContextFillRect(ctx, rect2);
    }
    

    Edit (because the question was edited):

    You can use this approach for dragging layers like this:

    • Draw a rectangle for each moving layer on a new layer or view on top of them, with the blend mode and drawing commands described above
    • Use the current frames of the moving layers for the drawing rects
    • Make sure that the new top layer doesn't receive touches
    • Redraw the new layer whenever the position of an interactive layer is changed