How to erase finger paint on Custom UIView in iPhone
Asked Answered
C

2

1

I have created a custom UIView (without .xib) for a finger paint application.

Paint is working fine with custom UIView but my problem is that when I try to erase the painted path I am getting:

Error : Invalid context

Below is my class:

.h file

@interface draw2D : UIView
{
    CGPoint previousPoint;
    CGPoint lastPoint;
    CGMutablePathRef path;
    UIButton *btnClose;
    UIButton *btnErase;
    BOOL IsErase;
}
- (IBAction)btnClose:(id)sender;
- (IBAction)btnErase:(id)sender;
@end


@implementation draw2D
- (void)awakeFromNib
{
    path = CGPathCreateMutable();
}
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) 
    {
        btnClose = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [btnClose addTarget:self action:@selector(btnClose:)
         forControlEvents:UIControlEventTouchDown];
        [btnClose setTitle:@"close" forState:UIControlStateNormal];
        btnClose.frame = CGRectMake(10, 10, 100, 40.0);

        btnErase = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        [btnErase addTarget:self action:@selector(btnErase:)
           forControlEvents:UIControlEventTouchDown];
        [btnErase setTitle:@"Erase" forState:UIControlStateNormal];
        btnErase.frame = CGRectMake(150, 10, 100, 40.0);

        [self addSubview:btnClose];
        [self addSubview:btnErase];
    }
    return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
{    
    UITouch *touch = [touches anyObject];
    NSLog(@"Touch Began :%d",[touch tapCount]);

    if ([touch tapCount] > 1) 
    {
        NSLog(@"::::: Paint Start :::::");
        path = CGPathCreateMutable();
        previousPoint = lastPoint;
        [self setNeedsDisplay];
    }
    self.backgroundColor = [UIColor clearColor];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event 
{
    NSLog(@"::::: touchesMoved :::::");
    lastPoint = [[touches anyObject] locationInView:self];
    previousPoint = [[touches anyObject] previousLocationInView:self];

    if(IsErase)
    {
        NSLog(@"erase");
        UITouch *erasetouch = [touches anyObject];  
        CGPoint erasecurrentPoint = [erasetouch locationInView:self];

        CGContextRef erasecontext = UIGraphicsGetCurrentContext();
        CGContextSetLineCap(erasecontext, kCGLineCapRound);
        CGContextSetLineWidth(erasecontext,10);
        CGContextSetBlendMode(erasecontext, kCGBlendModeClear);
        CGContextSetStrokeColorWithColor(erasecontext, [[UIColor clearColor] CGColor]);
        CGContextBeginPath(erasecontext);
        CGContextMoveToPoint(erasecontext, lastPoint.x, lastPoint.y);
        CGContextAddLineToPoint(erasecontext, erasecurrentPoint.x, erasecurrentPoint.y);
        CGContextStrokePath(erasecontext);     
        CGContextFlush(erasecontext);

    }  

    [self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
    NSLog(@"::::: drawRect :::::");

    CGContextRef context = UIGraphicsGetCurrentContext();
    CGPathMoveToPoint(path, NULL, previousPoint.x, previousPoint.y);
    CGPathAddLineToPoint(path, NULL, lastPoint.x, lastPoint.y);
    CGContextAddPath(context, path);
    CGContextSetLineWidth(context, 5);
    [[UIColor blueColor] setStroke];
    CGContextDrawPath(context, kCGPathFillStroke);
}

- (IBAction)btnClose:(id)sender
{
    [self removeFromSuperview];
}
- (IBAction)btnErase:(id)sender
{
    IsErase = YES;
}    

@end

I have set erase button with functionality but not working.

Complementary answered 21/6, 2012 at 6:17 Comment(1)
please check this answer this is realy work perfectly #3864431Eucken
C
1

finally i have find the solution . my mistake was i m implement erase code intouchMove method with new context . i dont have to need new context . implement erase code in drawrect method and now its working fine . see the below code.

- (void)drawRect:(CGRect)rect
{

    [curImage drawAtPoint:CGPointMake(0, 0)];
    CGPoint mid1 = midPoint(previousPoint1, previousPoint2); 
    CGPoint mid2 = midPoint(currentPoint, previousPoint1);

    context = UIGraphicsGetCurrentContext(); 
    [self.layer renderInContext:context];

    if(IsErase)
    {
        CGContextSetLineWidth(context,self.lineWidth);
        CGContextSetBlendMode(context, kCGBlendModeClear);
        CGContextSetStrokeColorWithColor(context, [[UIColor clearColor] CGColor]);
        CGContextBeginPath(context);
        CGContextMoveToPoint(context, mid1.x, mid1.y);
        CGContextAddLineToPoint(context, previousPoint1.x, previousPoint1.y);
        CGContextStrokePath(context);     
        CGContextFlush(context);
    }
    else
    {
        CGContextMoveToPoint(context, mid1.x, mid1.y);
        CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y); 
        CGContextSetLineCap(context, kCGLineCapRound);
        CGContextSetLineWidth(context, self.lineWidth);
        CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
        CGContextSaveGState(context);
        CGContextStrokePath(context);
    }
    [super drawRect:rect];
    [curImage release];
}

i hope it will helps to someone in erase functionality .

Complementary answered 23/6, 2012 at 5:21 Comment(0)
K
2

The problem you have is that you are not supposed to call UIGraphicGetContext() outside of drawRect:

In your touchesBegan:withEvent: and touchesMoved:withEvent: you should simply store the points you want to draw and call [self setNeedsDisplay] as you are doing now. In your drawRect: implementation you would then draw the points you have stored.

You can take a look at this github repo that provides an implementation for a smooth drawing:https://github.com/levinunnink/Smooth-Line-View

Katusha answered 21/6, 2012 at 10:2 Comment(1)
Thanks .. example helps me to make good fingure paint app . but yes what about Erase functionality ? how to implement in github demo ?Complementary
C
1

finally i have find the solution . my mistake was i m implement erase code intouchMove method with new context . i dont have to need new context . implement erase code in drawrect method and now its working fine . see the below code.

- (void)drawRect:(CGRect)rect
{

    [curImage drawAtPoint:CGPointMake(0, 0)];
    CGPoint mid1 = midPoint(previousPoint1, previousPoint2); 
    CGPoint mid2 = midPoint(currentPoint, previousPoint1);

    context = UIGraphicsGetCurrentContext(); 
    [self.layer renderInContext:context];

    if(IsErase)
    {
        CGContextSetLineWidth(context,self.lineWidth);
        CGContextSetBlendMode(context, kCGBlendModeClear);
        CGContextSetStrokeColorWithColor(context, [[UIColor clearColor] CGColor]);
        CGContextBeginPath(context);
        CGContextMoveToPoint(context, mid1.x, mid1.y);
        CGContextAddLineToPoint(context, previousPoint1.x, previousPoint1.y);
        CGContextStrokePath(context);     
        CGContextFlush(context);
    }
    else
    {
        CGContextMoveToPoint(context, mid1.x, mid1.y);
        CGContextAddQuadCurveToPoint(context, previousPoint1.x, previousPoint1.y, mid2.x, mid2.y); 
        CGContextSetLineCap(context, kCGLineCapRound);
        CGContextSetLineWidth(context, self.lineWidth);
        CGContextSetStrokeColorWithColor(context, self.lineColor.CGColor);
        CGContextSaveGState(context);
        CGContextStrokePath(context);
    }
    [super drawRect:rect];
    [curImage release];
}

i hope it will helps to someone in erase functionality .

Complementary answered 23/6, 2012 at 5:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.