Search code examples
iosobjective-ccore-graphicscore-animation

iOS graphics appearing from upper left corner on custom control


I have been making a circular control and i am doing fine, except that the graphics appears from upper left corner when i do the render first time.

The whole control is subclassed UIControl, with custom CALayer which does rendering of a circle.

This is the code that renders the circle:

- (void) drawInContext:(CGContextRef)ctx{
id modelLayer = [self modelLayer];
CGFloat radius = [[modelLayer valueForKey:DXCircularControlLayerPropertyNameRadius] floatValue];
CGFloat lineWidth = [[modelLayer valueForKey:DXCircularControlLayerPropertyNameLineWidth] floatValue];
//NSLog(@"%s, angle: %6.2f, radius: %6.2f, angle_m: %6.2f, radius_m: %6.2f", __func__, self.circleAngle, self.circleRadius, [[modelLayer valueForKey:@"circleAngle"] floatValue], [[modelLayer valueForKey:@"circleRadius"] floatValue]);

// draw circle arc up to target angle

CGRect frame = self.frame;
CGContextRef context = ctx;

CGContextSetShouldAntialias(context, YES);
CGContextSetAllowsAntialiasing(context, YES);

// draw thin circle

//CGContextSetLineWidth(context, <#CGFloat width#>)

// draw selection circle

CGContextSetLineWidth(context, lineWidth);
CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor);
CGContextAddArc(context, frame.size.width / 2.0f, frame.size.height / 2.0f, radius, 0.0f, self.circleAngle, 0);

CGContextStrokePath(context);

CGContextSetShouldAntialias(context, NO);
}

Here is the video of a problem.

If you watch carefully, you'll notice that rendering of circle somehow doesnt start centered. It skews itself from the upper left corner. This only happens when doing the animation for the first time.

I know this can happen if one mistakes begin and end of animation commit blocks, but i dont use them here.

Just in case here is the link to the bitbucket repo of this control:


Solution

  • There is nothing wrong with the drawing method - you messed up a little bit setting the layer's frame ;-)

    You are setting the frame for the circularControlLayer within your - (void) setAngle:(CGFloat)angle method. That means the frame is set for the first time when you animate the angle property - so the frame will be animated too. Set the frame within the - (void) commonInitDXCircularControlView method.

    If you are creating custom layers, have a look at the [UIView layerClass] method. Using it will save you from trouble with bounds/frame management.