Question

I have a custom UIControl that looks like:

enter image description here

The white ring is drawn in drawRect as follows:

//Get current context
CGContextRef mainContext = UIGraphicsGetCurrentContext();

/** Draw the Path **/

//Create the path
CGContextAddArc(mainContext, self.frame.size.width/2, self.frame.size.height/2, radius, 0, 2*M_PI, 0);

//Set the stroke color to white
[[UIColor whiteColor]setStroke];

//Define line width and cap
CGContextSetLineWidth(mainContext, HOUR_PICKER_BACKGROUND_WIDTH);
CGContextSetLineCap(mainContext, kCGLineCapButt);

//Draw the path
CGContextDrawPath(mainContext, kCGPathStroke);

The black circle is a CAShapeLayer and is drawn as follows:

hourSelector = [CAShapeLayer layer];
hourSelector.path = [UIBezierPath bezierPathWithRoundedRect:selectorPosition cornerRadius:11.0].CGPath;
hourSelector.fillColor = [UIColor colorWithRed:65.0f/255.0f green:75.0f/255.0f blue:86.0f/255.0f alpha:1.0f].CGColor;
hourSelector.strokeColor = [UIColor colorWithRed:65.0f/255.0f green:75.0f/255.0f blue:86.0f/255.0f alpha:1.0f].CGColor;
hourSelector.lineWidth = 1;
[self.layer addSublayer:hourSelector];

I have been able to implement the dragging of the black circle anywhere on the white ring. When I let the black circle go, I want to be able to animate the black circle to a certain position on the ring. When the finger is lifted off the circle, I have the value in radians of the ending touch position as well as the desired final position of the circles. I also have the points in rectangular/Cartesian coordinates. I'm trying to implement the desired behavior by drawing an arc between the two points and changing the position of the circle along the arc with a CAKeyFrameAnimation.

CAKeyframeAnimation *pathAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
pathAnimation.calculationMode = kCAAnimationPaced;
pathAnimation.fillMode = kCAFillModeForwards;
pathAnimation.removedOnCompletion = NO;
pathAnimation.duration = 1.0;


CGMutablePathRef arcPath = CGPathCreateMutable();
CGPathAddArc(arcPath, NULL, self.frame.size.width/2, self.frame.size.height/2, radius, endingTouchRadian, finalPositionRadian,0);

pathAnimation.path = arcPath;
CGPathRelease(arcPath);

[hourSelector addAnimation:pathAnimation forKey:@"moveHour"];

My issue is that the arc created is nowhere on the white ring. self.frame.size.height (and the corresponding width) is the same circle center used to create the white ring but the arc is created off the screen. Furthermore, using 0,0 for x,y does not return the top left of the frame but the exact center of the main window. The center of the arc circle also seems to change every time I rotate the circle and let go.

Am I missing out on how to get the center of the arc created to be the same as the center of the white circle?

Was it helpful?

Solution

I figured it out. I was creating the CGPath outside drawRect which was redrawing the view with a different origin. I don't understand what exactly was going on underneath but moving the CGPath creation code to drawRect resolved the issue. Thanks to @Unheilig for pointing me in the right direction with his comment.

OTHER TIPS

Wouldn't the center if your circle be

CGRectGetMidX(selectorPosition), CGRectGetMidY(selectorPosition)

You're using half the view's width and height, ignoring it's origin.

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