Alessandro
Alessandro

Reputation: 4100

Using TouchesMoved to draw a shape

I am trying to draw an arrow using my finger on the screen. the idea was that by touching the screen I set the initial coordinates of my arrow, and as I dragged on the screen the arrow would extend and follow my finger. the height and width of the arrow will be the same, its the size of the arrow that matters. The arrow will be longer as I drag it away from the starting point. I tried dong it with something like this:

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
    UIGraphicsBeginImageContext(CGSizeMake(1536, 2048));

    UITouch *touch = [touches anyObject];
    CGPoint p1 = [touch locationInView:self.view];

    CGSize size;
    size.width = 50;
    size.height = 400;

    CGContextRef context = UIGraphicsGetCurrentContext();

    [self drawArrowWithContext:context atPoint:p1 withSize:size lineWidth:4 arrowHeight:20 andColor:[UIColor whiteColor]];

    // converts your context into a UIImage
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();

    // Adds that image into an imageView and sticks it on the screen.
    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
    [self.view addSubview:imageView];
}

and

- (void) drawArrowWithContext:(CGContextRef)context atPoint:(CGPoint)startPoint withSize: (CGSize)size lineWidth:(float)width arrowHeight:(float)aheight andColor:(UIColor *)color
{
    float width_wing = (size.width - width) / 2;
    float main = size.height-aheight;

    CGContextSetFillColorWithColor(context, [color CGColor]);
    CGContextSetStrokeColorWithColor(context, [color CGColor]);

    CGPoint rectangle_points[] = {
        CGPointMake(startPoint.x + width_wing, startPoint.y + 0.0),
        CGPointMake(startPoint.x + width_wing, startPoint.y + main),
        CGPointMake(startPoint.x + 0.0, startPoint.y + main), // left point
        CGPointMake(startPoint.x + size.width / 2, startPoint.y + size.height),

        CGPointMake(startPoint.x + size.width, startPoint.y + main), // right point

        CGPointMake(startPoint.x + size.width-width_wing, startPoint.y + main),

        CGPointMake(startPoint.x + size.width-width_wing, startPoint.y + 0.0),
        CGPointMake(startPoint.x + width_wing, startPoint.y + 0.0),
    };

    CGContextAddLines(context, rectangle_points, 8);

    CGContextFillPath(context);
}

The arrow does appear on the screen if I run the code from the touches moved in a normal IBOutlet, but that was not the idea. I haven't managed to get this code to work yet, but I think that even if it worked, it would cause a crash, since I am deleting and redrawing the shape each time. Is this the right approach? What should I do?

Upvotes: 2

Views: 1026

Answers (2)

Nicopuri
Nicopuri

Reputation: 981

Yo can try to use UIPanGestureRecognizer to follow your finger and draw above of it.

Upvotes: 0

Christoph
Christoph

Reputation: 1525

Basically, there are some different options.

  • Stick to the UIImageView approach and stop recreating the image view all the time. Keep a reference to that UIImageView in the class detecting the touch events and just replace the image if something changed. Might be worth the extra effort for off-screen-drawing if you need the image for something else.
  • Implement the arrow drawing dynamically in an extra view.

The second one I will describe here briefly:

The class detecting the event needs a member variable/property, ArrowView *arrowView and something to remember the start point, CGPoint startPoint maybe. ArrowView needs properties for the arrow parameters, CGPoint arrowStart, CGSize arrowSize. In the touch event handler, do

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [touches anyObject];
    CGPoint position = [touch locationInView:self.view];

    [self.startPoint startFrom:position];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

    UITouch *touch = [touches anyObject];
    CGPoint next = [touch locationInView:self.view];

    CGSize size;
    size.width = next.x - self.startPoint.x;
    size.height = next.y - self.startPoint.y;

    self.arrowView.arrowPoint = self.startPoint;
    self.arrowView.arrowSize = size;

    [self.arrowView setNeedsDisplay];
}

In ArrowView:

- (void)drawRect:(CGRect)rect {
    [super drawRect:rect];

    CGContextRef context = UIGraphicsGetCurrentContext();
    // Now do the drawing stuff here using that context!
    // self.arrowSize / self.arrowPoint do contain your drawing parameters.
    ...
}

I hope that gives you an idea.

For further reading, start here.

Upvotes: 1

Related Questions