这里,我们利用- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 和- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
屏幕触摸事件实现只有清除,后退和保存的简单涂鸦板.首先 我们需要一个UIView作为这个涂鸦板,UIView上需要清除,后退和保存三个UIButton.我们还需要一个可变数组取保存我们每次画的线条.
#import "ScrawlView.h" #import "ColorView.h" #define BUTTONWIDTH ([[UIScreen mainScreen] bounds].size.width - 6)/5 // 本意要来5个Button,现在只有三个,此处不影响 #define HEIGHT 50 #define Y 30 @interface ScrawlView ( ) @property (nonatomic,retain)UIButton *backButtonScrawlView ; // 后退按钮 @property (nonatomic,retain)UIButton *clearAllButtonScrawlView ; // 一键清屏 @property (nonatomic,retain)UIButton *saveButtonScrawlView ; // 保存 @property (nonatomic,retain)NSMutableArray *allLineMutableArray ;// 保存所有线条的数组 @end
初始化方法,我们在这里初始化时直接把按钮加载进UIVIew(此时懒加载没有起到一定的作用)
// 初始化方法 - (instancetype)initWithFrame:(CGRect)frame { // 把大小设定成与屏幕一样大小,防止外部修改 CGRect fixedFrame = [[UIScreen mainScreen] bounds] ; if ([super initWithFrame:fixedFrame]) { [self addSubview:self.backButtonScrawlView] ; [self addSubview:self.clearAllButtonScrawlView] ; [self addSubview:self.saveButtonScrawlView] ; [self addSubview:self.fontColorButtonScrawlView] ; } return self ; } // 几个按钮的懒加载 -- get方法 // 后退按钮 - (UIButton *)backButtonScrawlView { if (!_backButtonScrawlView) { _backButtonScrawlView = [UIButton buttonWithType:UIButtonTypeSystem] ; _backButtonScrawlView.tag = backButtonTag ; _backButtonScrawlView.frame = CGRectMake(1, Y, BUTTONWIDTH, HEIGHT) ; [_backButtonScrawlView setTitle:@"后退" forState:UIControlStateNormal] ; [_backButtonScrawlView addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside] ; } return _backButtonScrawlView ; } // 清除按钮 - (UIButton *)clearAllButtonScrawlView { if (!_clearAllButtonScrawlView) { _clearAllButtonScrawlView = [UIButton buttonWithType:UIButtonTypeSystem] ; _clearAllButtonScrawlView.tag = clearButtonTag ; _clearAllButtonScrawlView.frame = CGRectMake(1+(1+BUTTONWIDTH), Y, BUTTONWIDTH, HEIGHT) ; [_clearAllButtonScrawlView setTitle:@"清空" forState:UIControlStateNormal] ; [_clearAllButtonScrawlView addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside] ; } return _clearAllButtonScrawlView ; } // 保存按钮 - (UIButton *)saveButtonScrawlView { if (!_saveButtonScrawlView) { _saveButtonScrawlView = [UIButton buttonWithType:UIButtonTypeSystem] ; _saveButtonScrawlView.tag = saveButtonTag ; _saveButtonScrawlView.frame = CGRectMake(1+(1+BUTTONWIDTH)*2, Y, BUTTONWIDTH, HEIGHT) ; [_saveButtonScrawlView setTitle:@"保存" forState:UIControlStateNormal] ; [_saveButtonScrawlView addTarget:self action:@selector(clickButton:) forControlEvents:UIControlEventTouchUpInside] ; } return _saveButtonScrawlView ; }
懒加载就够避免多次创建对象,因此为了保证保存线条数组的唯一性,我们使用懒加载(重写它的get方法)
// 保存线条的数组 - (NSMutableArray *)allLineMutableArray { if (!_allLineMutableArray) { _allLineMutableArray = [[NSMutableArray alloc] init] ; } return _allLineMutableArray ; }
接下来就该响应者链的触摸事件了.开始触摸时就响应 :- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
//开始触摸 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { // 获得触摸对象 UITouch *touch = touches.anyObject ; // 获得触摸的点 CGPoint startPoint = [touch locationInView:self.superview] ; // 初始化一个UIBezierPath对象,用来存储所有的轨迹点 UIBezierPath *bezierPath = [UIBezierPath bezierPath] ; // 把起始点存储到UIBezierPath对象中 [bezierPath moveToPoint:startPoint] ; // 把当前UIBezierPath对象存储到数组中 [self.allLineMutableArray addObject:bezierPath] ; }
触控完成之后的移动,只要触控点在移动,这个方法会多次调用.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { // 获取触摸对象 UITouch *touch = touches.anyObject ; // 获得当前的点 CGPoint currentPoint = [touch locationInView:self.superview] ; // 获得数组中的最后一个UIBezierPath对象(因为我们每次都把UIBezierPath存入到数组最后一个,因此获取时也取最后一个) UIBezierPath *bezierPath = self.allLineMutableArray.lastObject ; // 把当前点加入到bezierPath中 [bezierPath addLineToPoint:currentPoint] ; // 每移动一次就重新绘制当前视图 [self setNeedsDisplay] ;// 调用此方法,就会触发drawrect来重新绘制当前视图. }
重新绘制当前视图的方法
// 重新绘制当前视图 - (void)drawRect:(CGRect)rect { [[UIColor redColor] setStroke] ; // 设置画笔颜色 for (UIBezierPath *bezierPath in self.allLineMutableArray) { bezierPath.lineWidth = 3 ;// 设置画笔线条粗细 [bezierPath stroke] ; // 划线 } }
当我们想要点击按钮响应事件时 :
// 按钮点击事件 - (void)clickButton : (UIButton *)sender { // 后退按钮 if (sender.tag == backButtonTag) //tag值我们预设为枚举值类型 { if (_allLineMutableArray && [_allLineMutableArray count] > 0) { // 清除数组最后一个UIBezierPath对象 [self.allLineMutableArray removeLastObject] ; // 重新绘制 [self setNeedsDisplay] ; } } else if(sender.tag == clearButtonTag) // 清除按钮 { if (_allLineMutableArray&&[_allLineMutableArray count]) { //清空数组中所有元素 [self.allLineMutableArray removeAllObjects] ; // 重新绘制 [self setNeedsDisplay] ; } } else if (sender.tag == saveButtonTag)// 保存按钮 { // 得到把将要保存的图片 UIImage *image = [self getImageUIView] ; // 把图片保存到手机的photo相册中 UIImageWriteToSavedPhotosAlbum(image, self, nil, nil) ; } }
保存图片的方法
// 得到当前View上绘制的图像 - (UIImage *)getImageUIView { // 创建bitmap图形上下文 UIGraphicsBeginImageContext(self.frame.size) ; // 将要保存的View的layer绘制到bitmap图形上下文中 [self.layer renderInContext:UIGraphicsGetCurrentContext()] ; // 取出绘制好的图片 UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext(); // 关闭图形上下文 UIGraphicsEndImageContext() ; // 返回获取的图片 return newImage ; }
上面我们用到的枚举值类型为
typedef enum AllButtonTag { backButtonTag = 1000 , // 后退 clearButtonTag = 1001 , // 清除 saveButtonTag = 1002 , // 保存 }btnTag;