shadowhorst
shadowhorst

Reputation: 1500

UIBezierPath containsPoint not working with touchesBegan

I'm drawing a filled shape using the UIBezierPath and i want to check if a user touches this shape. Here is my code:

- (void)drawRect:(CGRect)rect
{ 
aShape = [UIBezierPath bezierPathWithOvalInRect:
 CGRectMake(0, 0, 200, 100)];

[[UIColor blackColor] setStroke];
[[UIColor redColor] setFill];

CGContextRef aRef = UIGraphicsGetCurrentContext();

CGContextTranslateCTM(aRef, 50, 50);

aShape.lineWidth = 5;

[aShape fill];
[aShape stroke];

 CGPoint x = CGPointMake(30, 40);
 if([aShape containsPoint:x]) {
 NSLog(@"in");
 } else {
 NSLog(@"out");
}
}
  - (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
}
return self;
}


- (void)dealloc {
 [aShape dealloc];
[super dealloc];
}

-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
 UITouch *t = [[touches allObjects] objectAtIndex:0];
CGPoint p = [t locationInView:self];
[aShape containsPoint:p];
}

@end

I have some issues with the :containsPoint method. It is working in the drawRect-Code, but not in the touchesBegan method and I don't know why :( I would appreciate some help...Thx.

Upvotes: 0

Views: 1671

Answers (2)

Joshua Barker
Joshua Barker

Reputation: 1007

For those having the same problem in Xamarin / MonoTouch, here is a similar solution:

public class FooControl : UIControl
{
    private float _xOffset;
    private float _yOffset;
    private UIBezierPath _path;

    public FooControl(RectangleF frame) : this(frame)
    {
        //offsets to move drawing origin to center of containing frame
        _xOffset = Frame.Width / 2;
        _yOffset = Frame.Height / 2;
    }

    public override void Draw(RectangleF rect)
    {
        base.Draw(rect);

        using(CGContext g = UIGraphics.GetCurrentContext())
        {
             // move origin to middle of screen
             g.TranslateCTM(_xOffset, _yOffset);

             if (_path == null)
             {
                 _path = new UIBezierPath();

                //... build rest of path ...

                _path.Close();
             }

            //... rest of drawing code goes here ...
        }
    }

    public override UIView HitTest(PointF touchPoint, UIEvent uiEvent)
    {
        if (_path != null)
        {
            //important! to reverse original translation, use negative values
            CGAffineTransform affine = 
                CGAffineTransform.MakeTranslation(-_xOffset, -_yOffset);

            PointF localPoint = affine.TransformPoint(touchPoint);
            if (_path.ContainsPoint(localPoint))
            {
                return this;
            }
        }

        return null;
    }
}

Upvotes: 0

Joshua Weinberg
Joshua Weinberg

Reputation: 28688

If I had to venture a guess, it isn't working as you expect in touchesBegan because you're not accounting for the fact that you drew the path offset. [aShape containsPoint:p] isn't going to know about the context transform you applied previously.

On a slightly different note, [aShape dealloc] you should never call dealloc on an object directly. The only time you call dealloc is on super at the end of your own dealloc. This line should be [aShape release]

Upvotes: 4

Related Questions