UIBezierPath bar touch detection, not padding

Possible duplicate:
How to verify that a user is connected to CGPath?

I follow the Apple manual here

http://developer.apple.com/library/ios/#documentation/2DDrawing/Conceptual/DrawingPrintingiOS/BezierPaths/BezierPaths.html

to try to detect a touch event only on the stroked part of my UIBezierPath. If I use the UIBezierPath, containsPoint method, it works fine, but it detects touch events on the bar and the fill part of UIBezierPath, and I want this to happen only on the stroked part.

Following Apple's guidance (in 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 0x0

Here is my view of drawRect, 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]; } 

Then I try to call the containsPoint function inside touchphonesMoved, for example:

 if (![self containsPoint:c onPath:[self createPath] inFillArea:NO]) return; 
+6
source share
2 answers

If you are not currently drawing (as in the touchesMoved method), then there is no current context, so UIGraphicsGetCurrentContext() will return NULL.

Since everything you do with the context should use its current path, you can simply use CGPathContainsPoint instead of CGContextPathContainsPoint .

+4
source

The Apple example assumes that you are working inside a graphical context. This is not so, so you can simply 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 ran into the same problem and it fixed it for me!

+1
source

Source: https://habr.com/ru/post/889164/


All Articles