设计一个画板,起名为:LYDrawBoard
1、先设计几个属性
//用于存放路径
@property(nonatomic,retain)NSMutableArray * points;
//画线的宽度 这里用IBInspectable来将该属性绑定到IB
@property(nonatomic,assign)IBInspectable CGFloat lineWidth;
//线的颜色
@property(nonatomic,strong)IBInspectable UIColor * color;
2、设计两个方法供外部使用
//退回到上一步
- (void)back;
//擦除所有
- (void)clear;
3、通过懒加载(实质是getter方法)来初始化points数组
//MARK: - lazy
- (NSMutableArray *)points
{
if (_points == nil) {
_points = [NSMutableArray array];
}
return _points;
}
4、通过getter方法来设置默认属性
//默认宽度
#define kDefaultWidth 6
//默认颜色
#define kDefaultColor [UIColor blackColor]
//MARK: - default
- (CGFloat)lineWidth{
if (!_lineWidth) {
_lineWidth = kDefaultWidth;
}
return _lineWidth;
}
- (UIColor *)color{
if (!_color) {
_color = kDefaultColor;
}
return _color;
}
5、UIView是可以接受用户触摸事件的,可以通过touches方法来实现笔画路径的记录
首先,通过下面这个方法确定起点,即开始触摸时触发的方法:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;//触摸开始时触发
过程如下,最后用下面这个方法来调用重绘视图(即通知系统调用drawRect):
[self setNeedsDisplay];//刷新帧
确定起点:
/**
* 确定起点
*/
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint startPos = [touch locationInView:touch.view];
//添加路径
UIBezierPath *path = [UIBezierPath bezierPath];
//设置路径的起始点为圆点
path.lineCapStyle = kCGLineCapRound;
//设置路径的结束点为圆点
path.lineJoinStyle = kCGLineJoinRound;
//路径的起始点用 moveToPoint:
[path moveToPoint:startPos];
[self.points addObject:path];
//刷新帧
[self setNeedsDisplay];
}
其次是将路径连线:
通过下面这个方法来实现移动过程中,路径的连线:
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;//移动时触发
连线:
/**
* 连线
*/
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint currentPos = [touch locationInView:touch.view];
UIBezierPath *currentPath = self.points.lastObject;
[currentPath addLineToPoint:currentPos];
//刷新帧
[self setNeedsDisplay];
}
触摸结束时:
/**
* 结束时也调用touchesMoved来将终点连线
*/
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesMoved:touches withEvent:event];
}
重绘方法:
/**
* 重绘
*/
-(void)drawRect:(CGRect)rect
{
//先设置颜色
[self.color set];
//遍历所有path,设置宽度,并分别调用stroke
for (UIBezierPath *path in self.points) {
path.lineWidth = self.lineWidth;
[path stroke];
}
}
设计一个签名板的App:
至此LYDrawBoard画板设计好了,我们可以设计一个简单的画板app了,并添加三个按钮,回退,清除,完成,运行效果图如下:
上一步按钮触发方法:
//上一步
- (IBAction)previous:(id)sender {
[_pointView back];
}
清除按钮触发方法:
//清除
- (IBAction)clear:(id)sender {
[_pointView clear];
}
给UIView增加一个类方法(用类别),截图当前视图,当点击完成时,判断points是否为空,不为空则说明,有笔画,可截图传递给下一页图片浏览器,否则不截图传递,类别方法如下:
//截图
+(UIImage*)captureWithView:(UIView *)view
{
//开启上下文
UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, 0.0);
//将控制器的view的layer渲染到上下文
[view.layer renderInContext:UIGraphicsGetCurrentContext()];
// 取出图片
UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
//结束上下文
UIGraphicsEndImageContext();
return newImage;
}
在故事版传递的函数中即可判断,如下所示:
//传递image
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
PhotoViewController * pvc = (PhotoViewController *)segue.destinationViewController;
if (_pointView.points.count) {
pvc.image = [UIView captureWithView:_pointView];
}
}
点击完成后,运行效果如下:
在图片浏览器界面增加保存按钮,可以将截图保存到相册,方法如下:
- (IBAction)save:(id)sender {
/**
* 将图片保存到iPhone本地相册
* UIImage *image 图片对象
* id completionTarget 响应方法对象
* SEL completionSelector 方法
* void *contextInfo
*/
UIImageWriteToSavedPhotosAlbum(_image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
}
并实现保存后的响应方法:
//响应对象
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo{
NSString * msg = nil;
if (error == nil) {
msg = @"保存成功";
}else{
msg = @"保存失败";
}
[self showAlertForMsg:msg];
}
提示弹框:
//提示框
- (void)showAlertForMsg:(NSString *)msg{
UIAlertController * alertC = [UIAlertController alertControllerWithTitle:@"提示" message:msg preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction * action = [UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
}];
[alertC addAction:action];
[self presentViewController:alertC animated:true completion:nil];
}