Detect touch on UIBezierPath stroke, not fill [duplicate]
Possible Duplicate:
How can I check if a user tapped near a CGPath?
I'm following Apple's guide from here
http://developer.apple.com/library/ios/#documentation/2DDrawing/Conceptual/DrawingPrintingiOS/BezierPaths/BezierPaths.html
to try and detect a touch event only on the stroked portion of my UIBezierPath.开发者_StackOverflow If I use the UIBezierPath method, containsPoint, it works fine, but it detects touch events on the stroke and the fill portion of the UIBezierPath, and I want it to only occur on the stroked portion.
Following Apple's guide (at listing 3-6 of the link), I created this function:
- (BOOL)containsPoint:(CGPoint)point onPath:(UIBezierPath*)path inFillArea:(BOOL)inFill
{
CGContextRef context = UIGraphicsGetCurrentContext();
CGPathRef cgPath = path.CGPath;
BOOL isHit = NO;
// Determine the drawing mode to use. Default to
// detecting hits on the stroked portion of the path.
CGPathDrawingMode mode = kCGPathStroke;
if (inFill)
{
// Look for hits in the fill area of the path instead.
if (path.usesEvenOddFillRule)
mode = kCGPathEOFill;
else
mode = kCGPathFill;
}
// Save the graphics state so that the path can be
// removed later.
CGContextSaveGState(context);
CGContextAddPath(context, cgPath);
// Do the hit detection.
isHit = CGContextPathContainsPoint(context, point, mode);
CGContextRestoreGState(context);
return isHit;
}
When I call it, I get:
Error: CGContextSaveGState: invalid context 0x0
Error: CGContextAddPath: invalid context 0x0 Error: CGContextPathContainsPoint: invalid context 0x0 Error: CGContextRestoreGState: invalid context 0x0Here's my view's drawRect function, and my code to create my path:
- (UIBezierPath *) createPath {
static UIBezierPath *path = nil;
if(!path) {
path = [[UIBezierPath bezierPathWithOvalInRect:CGRectMake(35, 45, 250, 250)] retain];
path.lineWidth = 50.0;
[path closePath];
}
return path;
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
*/
- (void)drawRect:(CGRect)rect
{
// Drawing code
//draw a circle
UIBezierPath *aPath = [self createPath];
//set stroke width
aPath.lineWidth = 50.0;
//set stroke color
[[UIColor blueColor] setStroke];
//stroke path
[aPath stroke];
//close path
[aPath closePath];
//add a label at the "top"
UILabel *topLabel;
topLabel = [[UILabel alloc]initWithFrame:CGRectMake(120, -5, 80, 25)];
topLabel.text = @"The Top";
[self addSubview:topLabel];
}
I'm then trying to call the containsPoint function inside of touchesMoved, like this:
if (![self containsPoint:c onPath:[self createPath] inFillArea:NO]) return;
When you're currently not drawing (as in the touchesMoved
method), there is no current context, so UIGraphicsGetCurrentContext()
will return NULL.
As all you're doing with the context is to use its current path, you could just as well use CGPathContainsPoint
instead of CGContextPathContainsPoint
.
Apple's example assumes you're working inside a graphics context. You're not, so you can just add two lines to the method:
UIGraphicsBeginImageContext(self.frame.size); // ADD THIS...
CGContextRef context = UIGraphicsGetCurrentContext(); // ...before this
and
CGContextRestoreGState(context); // after this...
UIGraphicsEndImageContext(); // ADD THIS
I just ran into the same problem, and this fixed it for me!
精彩评论