[iOS UI进阶 - 4.0] 涂鸦app Demo

A.需求
1.超简易画图,只有一种画笔
2.清屏功能
3.回退功能
4.保存功能
5.使用了cocos2D
 
 
技术分享
 
B.实现方法1
1.基本界面
(1)3个按钮:清屏、回退、保存
(2)绘图view
技术分享
 
2.画线
(1)使用数组存储绘图点:存储一条线的数组、存储所有线的总数组
(2)在touch的开始、拖曳、结束记录触摸位置,触发重绘
 
3.清屏
删除总数组
 
4.回退
删除最后画的一条线:删除相应数组
 
5.保存到相册
使用”截图”功能,保存绘图view
 
  1 //
  2 //  PaintView.m
  3 //  PaintDemo
  4 //
  5 //  Created by hellovoidworld on 15/1/10.
  6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
  7 //
  8 
  9 #import "PaintView.h"
 10 #import "UIImage+Extension.h"
 11 
 12 @interface PaintView()
 13 
 14 @end
 15 
 16 @implementation PaintView
 17 
 18 - (NSMutableArray *)lines {
 19     if (nil == _lines) {
 20         _lines = [NSMutableArray array];
 21     }
 22     return _lines;
 23 }
 24 
 25 #pragma mark - 触摸事件
 26 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
 27     UITouch *touch = [touches anyObject];
 28     CGPoint startLocation = [touch locationInView:touch.view];
 29    
 30     // 开启一条新的线
 31     NSMutableArray *points = [NSMutableArray array];
 32     // 存储点信息到线上
 33     [points addObject:[NSValue valueWithCGPoint:startLocation]];
 34     // 存储到线组上
 35     [self.lines addObject:points];
 36    
 37     // 重绘
 38     [self setNeedsDisplay];
 39 }
 40 
 41 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
 42     UITouch *touch = [touches anyObject];
 43     CGPoint location = [touch locationInView:touch.view];
 44    
 45     // 拿到正在画的线
 46     NSMutableArray *points = [self.lines lastObject];
 47     // 添加点信息
 48     [points addObject:[NSValue valueWithCGPoint:location]];
 49    
 50     // 重绘
 51     [self setNeedsDisplay];
 52 }
 53 
 54 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
 55     // 停止拖曳的逻辑其实和拖曳中是一样的
 56     [self touchesMoved:touches withEvent:event];
 57 }
 58 
 59 #pragma mark - 绘图方法
 60 /** 绘图 */
 61 - (void)drawRect:(CGRect)rect {
 62     CGContextRef ctx = UIGraphicsGetCurrentContext();
 63    
 64     // 遍历线组,把所有线画出来
 65     for (NSArray *line in self.lines) {
 66         for (int i=0; i<line.count; i++) {
 67             NSValue *pointValue = line[i];
 68             CGPoint point = [pointValue CGPointValue];
 69            
 70             // 如果是线的第一个点,要先移动画笔到那个点
 71             if (0 == i) {
 72                 CGContextMoveToPoint(ctx, point.x, point.y);
 73             } else {
 74                 CGContextAddLineToPoint(ctx, point.x, point.y);
 75             }
 76         }
 77     }
 78    
 79     // 设置线宽、线头样式、线转折样式
 80     CGContextSetLineWidth(ctx, 5);
 81     CGContextSetLineCap(ctx, kCGLineCapRound);
 82     CGContextSetLineJoin(ctx, kCGLineJoinRound);
 83    
 84     // 渲染
 85     CGContextStrokePath(ctx);
 86 }
 87 
 88 #pragma mark - view操作方法
 89 /** 回退 */
 90 - (void)rollback {
 91     [self.lines removeLastObject];
 92     [self setNeedsDisplay];
 93 }
 94 
 95 /** 清屏 */
 96 - (void)clearScreen {
 97     [self.lines removeAllObjects];
 98     [self setNeedsDisplay];
 99 }
100 
101 /** 保存 */
102 - (void)save {
103     // 1.获取图片
104     UIImage *image = [UIImage imageOfView:self];
105    
106     // 2.保存图片到相册
107     UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
108 }
109 
110 /** 保存图片后激发事件
111 * 这是文档推荐的方法
112 */
113 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
114     if (error) {
115         NSLog(@"保存失败");
116     } else {
117         NSLog(@"保存成功");
118     }
119 }
120 
121 @end
 
 1 //
 2 //  UIImage+Extension.m
 3 //  PaintDemo
 4 //
 5 //  Created by hellovoidworld on 15/1/11.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import "UIImage+Extension.h"
10 
11 @implementation UIImage(Extension)
12 
13 + (UIImage *) imageOfView:(UIView *) view {
14     // 1.开启图片上下文
15     UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, 0.0);
16    
17     // 2.将view的layer渲染到上下文
18     [view.layer renderInContext:UIGraphicsGetCurrentContext()];
19    
20     // 3.获取上下文中的图片
21     UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
22    
23     // 4.关闭图片上下文
24     UIGraphicsEndImageContext();
25    
26     return image;
27 }
28 
29 @end
 
C.实现方法2
1.基本界面和方法1一样
 
2.画线
(1)使用贝塞尔路径UIBezierPath,一条线就是一个UIBezierPath对象
(2)同样使用数组来存储UIBezierPath对象
 
3.清屏、回退、保存和方法1一样
 
  1 //
  2 //  BezierPaintView.m
  3 //  PaintDemo
  4 //
  5 //  Created by hellovoidworld on 15/1/11.
  6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
  7 //
  8 
  9 #import "BezierPaintView.h"
 10 #import "UIImage+Extension.h"
 11 
 12 @implementation BezierPaintView
 13 
 14 - (NSMutableArray *)lines {
 15     if (nil == _lines) {
 16         _lines = [NSMutableArray array];
 17     }
 18     return _lines;
 19 }
 20 
 21 #pragma mark - 触摸事件
 22 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
 23     UITouch *touch = [touches anyObject];
 24     CGPoint startLocation = [touch locationInView:touch.view];
 25    
 26     // 新建一条Bezier线
 27     UIBezierPath *path = [UIBezierPath bezierPath];
 28     [path setLineWidth:5.0];
 29     [path setLineCapStyle:kCGLineCapRound];
 30     [path setLineJoinStyle:kCGLineJoinRound];
 31    
 32     // 移动到始点
 33     [path moveToPoint:startLocation];
 34     // 添加Bezier线到数组
 35     [self.lines addObject:path];
 36    
 37     // 重绘
 38     [self setNeedsDisplay];
 39 }
 40 
 41 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
 42     UITouch *touch = [touches anyObject];
 43     CGPoint location = [touch locationInView:touch.view];
 44    
 45     // 获得正在画的线
 46     UIBezierPath *path = [self.lines lastObject];
 47     // 画线-添加点信息
 48     [path addLineToPoint:location];
 49    
 50     // 重绘
 51     [self setNeedsDisplay];
 52 }
 53 
 54 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
 55     // 停止拖曳的逻辑其实和拖曳中是一样的
 56     [self touchesMoved:touches withEvent:event];
 57 }
 58 
 59 #pragma mark - 绘图方法
 60 /** 绘图 */
 61 - (void)drawRect:(CGRect)rect {
 62    
 63     // 画出所有的线
 64     for (UIBezierPath *path in self.lines) {
 65         // 渲染
 66         [path stroke];
 67     }
 68    
 69 }
 70 
 71 #pragma mark - view操作方法
 72 /** 回退 */
 73 - (void)rollback {
 74     [self.lines removeLastObject];
 75     [self setNeedsDisplay];
 76 }
 77 
 78 /** 清屏 */
 79 - (void)clearScreen {
 80     [self.lines removeAllObjects];
 81     [self setNeedsDisplay];
 82 }
 83 
 84 /** 保存 */
 85 - (void)save {
 86     // 1.获取图片
 87     UIImage *image = [UIImage imageOfView:self];
 88    
 89     // 2.保存图片到相册
 90     UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
 91 }
 92 
 93 /** 保存图片后激发事件
 94 * 这是文档推荐的方法
 95 */
 96 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
 97     if (error) {
 98         NSLog(@"保存失败");
 99     } else {
100         NSLog(@"保存成功");
101     }
102 }
103 
104 @end
 
 
 
D.附加功能
  • slider控件调整线宽
  • 选择颜色
 
技术分享
 
1.slider调整线宽
(1)使用slider控件
(2)通过slider的valueChange事件调用方法设置线宽
 
2.选择颜色
(1)创建一个“色块”类
  • 使用UIView作为色块
  • 自定义一个继承UIView的类,作为色块class,给色块UIView加上点击事件
  • 给色块UIView创建一个颜色属性和代理协议,代理是ViewController;创建一个点击代理事件方法
 1 //
 2 //  ColorSelectionView.h
 3 //  PaintDemo
 4 //
 5 //  Created by hellovoidworld on 15/1/11.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 
11 @protocol ColorSelectionViewDelegate <NSObject>
12 
13 /** “色块”点击代理方法 */
14 @optional
15 - (void) selectColor:(UIColor *) selectedColor;
16 
17 @end
18 
19 @interface ColorSelectionView : UIView
20 
21 /** 代理 */
22 @property(nonatomic, strong) id<ColorSelectionViewDelegate> delegate;
23 
24 @end
25  
26 //
27 //  ColorSelectionView.m
28 //  PaintDemo
29 //
30 //  Created by hellovoidworld on 15/1/11.
31 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
32 //
33 
34 #import "ColorSelectionView.h"
35 
36 @implementation ColorSelectionView
37 
38 - (void)awakeFromNib {
39     // 给UIView设置点击事件
40     UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(colorClicked)];
41     [self addGestureRecognizer:tapGesture];
42 }
43 
44 /** “色块”点击事件 */
45 - (void) colorClicked {
46     [self.delegate selectColor:self.backgroundColor];
47 }
48 
49 @end
 
(2)自定义一个继承UIBezierPath的类,增加一个线颜色的属性
 1 //
 2 //  HVWBezierPath.h
 3 //  PaintDemo
 4 //
 5 //  Created by hellovoidworld on 15/1/11.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import <UIKit/UIKit.h>
10 
11 @interface HVWBezierPath : UIBezierPath
12 
13 /** 颜色 */
14 @property(nonatomic, strong) UIColor *color;
15 
16 @end
 
(3)ViewController代理“色块”的点击事件
  • 拖入所有“色块”对象到ViewController,设置代理
  • 遵守“色块”协议,实现代理方法
 
 1 //
 2 //  ViewController.m
 3 //  PaintDemo
 4 //
 5 //  Created by hellovoidworld on 15/1/10.
 6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
 7 //
 8 
 9 #import "ViewController.h"
10 #import "BezierPaintView.h"
11 #import "ColorSelectionView.h"
12 
13 @interface ViewController () <ColorSelectionViewDelegate>
14 
15 @property (weak, nonatomic) IBOutlet BezierPaintView *paintView;
16 
17 /** 颜色选择集合 */
18 @property (strong, nonatomic) IBOutletCollection(ColorSelectionView) NSArray *colorSelection;
19 
20 - (IBAction)rollback;
21 - (IBAction)clearScreen;
22 - (IBAction)save;
23 - (IBAction)lineWidthChange:(UISlider *)sender;
24 
25 @end
26 
27 @implementation ViewController
28 
29 - (void)viewDidLoad {
30     [super viewDidLoad];
31     // Do any additional setup after loading the view, typically from a nib.
32    
33     // 设置颜色选择器的代理
34     for (ColorSelectionView *colorView in self.colorSelection) {
35         colorView.delegate = self;
36     }
37 }
38 
39 - (void)didReceiveMemoryWarning {
40     [super didReceiveMemoryWarning];
41     // Dispose of any resources that can be recreated.
42 }
43 
44 /** 回退 */
45 - (IBAction)rollback {
46     [self.paintView rollback];
47 }
48 
49 /** 清屏 */
50 - (IBAction)clearScreen {
51     [self.paintView clearScreen];
52 }
53 
54 /** 保存 */
55 - (IBAction)save {
56     [self.paintView save];
57 }
58 
59 /** 改变线粗 */
60 - (IBAction)lineWidthChange:(UISlider *)sender {
61     self.paintView.lineWidth = sender.value;
62 }
63 
64 #pragma mark - ColorSelectionViewDelegate 代理方法
65 - (void) selectColor:(UIColor *) selectedColor {
66     self.paintView.lineColor = selectedColor;
67 }


@end
 
(4)“画板”在开始画一条线的时候(触摸开始),设置线宽和颜色
  1 //
  2 //  BezierPaintView.m
  3 //  PaintDemo
  4 //
  5 //  Created by hellovoidworld on 15/1/11.
  6 //  Copyright (c) 2015年 hellovoidworld. All rights reserved.
  7 //
  8 
  9 #import "BezierPaintView.h"
 10 #import "UIImage+Extension.h"
 11 #import "HVWBezierPath.h"
 12 
 13 @interface BezierPaintView()
 14 
 15 @end
 16 
 17 @implementation BezierPaintView
 18 
 19 - (NSMutableArray *)lines {
 20     if (nil == _lines) {
 21         _lines = [NSMutableArray array];
 22     }
 23     return _lines;
 24 }
 25 
 26 #pragma mark - 触摸事件
 27 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
 28     UITouch *touch = [touches anyObject];
 29     CGPoint startLocation = [touch locationInView:touch.view];
 30    
 31     // 新建一条Bezier线
 32     HVWBezierPath *path = [[HVWBezierPath alloc] init];
 33    
 34     // 配置线粗
 35     if (self.lineWidth) {
 36         [path setLineWidth:self.lineWidth];
 37     }
 38    
 39     // 配置线色
 40     if (self.lineColor) {
 41         path.color = self.lineColor;
 42     }
 43    
 44     [path setLineCapStyle:kCGLineCapRound];
 45     [path setLineJoinStyle:kCGLineJoinRound];
 46    
 47     // 移动到始点
 48     [path moveToPoint:startLocation];
 49     // 添加Bezier线到数组
 50     [self.lines addObject:path];
 51    
 52     // 重绘
 53     [self setNeedsDisplay];
 54 }
 55 
 56 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
 57     UITouch *touch = [touches anyObject];
 58     CGPoint location = [touch locationInView:touch.view];
 59    
 60     // 获得正在画的线
 61     HVWBezierPath *path = [self.lines lastObject];
 62     // 画线-添加点信息
 63     [path addLineToPoint:location];
 64    
 65     // 重绘
 66     [self setNeedsDisplay];
 67 }
 68 
 69 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
 70     // 停止拖曳的逻辑其实和拖曳中是一样的
 71     [self touchesMoved:touches withEvent:event];
 72 }
 73 
 74 #pragma mark - 绘图方法
 75 /** 绘图 */
 76 - (void)drawRect:(CGRect)rect {
 77    
 78     // 画出所有的线
 79     for (HVWBezierPath *path in self.lines) {
 80 
 81         // 设置颜色
 82         if (path.color) {
 83             [path.color set];
 84         }
 85        
 86         // 渲染
 87         [path stroke];
 88     }
 89    
 90 }
 91 
 92 #pragma mark - view操作方法
 93 /** 回退 */
 94 - (void)rollback {
 95     [self.lines removeLastObject];
 96     [self setNeedsDisplay];
 97 }
 98 
 99 /** 清屏 */
100 - (void)clearScreen {
101     [self.lines removeAllObjects];
102     [self setNeedsDisplay];
103 }
104 
105 /** 保存 */
106 - (void)save {
107     // 1.获取图片
108     UIImage *image = [UIImage imageOfView:self];
109    
110     // 2.保存图片到相册
111     UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
112 }
113 
114 /** 保存图片后激发事件
115 * 这是文档推荐的方法
116 */
117 - (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
118     if (error) {
119         NSLog(@"保存失败");
120     } else {
121         NSLog(@"保存成功");
122     }
123 }
124 
125 
126 @end

 

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。