问题
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.
回答1:
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
回答2:
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 .
来源:https://stackoverflow.com/questions/11132546/how-to-erase-finger-paint-on-custom-uiview-in-iphone