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

A.需求

1.超简易画图,只有一种画笔

2.清屏功能

3.回退功能

4.保存功能

5.使用了cocos2D

code source: https://github.com/hellovoidworld/PaintDemo

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
时间: 01-09

[iOS UI进阶 - 4.0] 涂鸦app Demo的相关文章

[iOS UI进阶 - 5.0] 手势解锁Demo

A.需求 1.九宫格手势解锁 2.使用了绘图和手势事件 code source: https://github.com/hellovoidworld/GestureUnlockDemo B.实现 使用按钮来处理每个圆点 使用代码生成按钮 取消按钮点击事件 设置普通状态和选中状态的背景图片 CGRectContainsPoint,移动到按钮范围内改变按钮为选中状态 按钮的连接:使用数组存储被选中的所有按钮,画上连线 已经连线的按钮不需要再连线 触摸结束清空连线和按钮选中状态 移动中也要画出线,最后

[iOS UI进阶 - 2.0] 彩票Demo v1.0

A.需求 1.模仿"网易彩票"做出有5个导航页面和相应功能的Demo 2.v1.0 版本搭建基本框架 B.搭建基本框架 1.拖入TaBarController,5个NavigationController和对应的5个UIViewController 2.配置图标和启动画面 AppIcon直接拖入图片 LaunchImage在Xcode6中需要先更改启动图使用图库的图片,而不是LaunchImage.xib 2.引入图片包 4. 按照模块分类代码包 3.底部导航--自定义TabBar (

[iOS UI进阶 - 3.0] 触摸事件的基本处理

A.需要掌握和练习的 1.介绍事件类型2.通过按钮的事件处理引出view的事件处理3.响应者对象 --> UIResponder --> UIView4.view的拖拽* 实现触摸方法,打印查看* 介绍touches和UIEvent参数* 扩展:点哪去哪5.涂鸦6.手势解锁7.事件的产生和传递8.响应者链条 9.手势 B.概念 1.iOS有3种主要事件 触摸事件 加速计事件 远程控制事件 2.响应者对象 在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事

iOS UI进阶-1.0 Quartz2D

概述 Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统.Quartz 2D能完成的工作: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成PDF 截图\裁剪图片 自定义UI控件 代码实现 绘制线条 #import "LineView.h" @implementation LineView -(void)drawRect:(CGRect)rect { // Drawing code // 1.获得图形上下文 CGContextRef

iOS UI进阶-4.0 地图与定位

在移动互联网时代,移动app能解决用户的很多生活琐事,比如 导航:去任意陌生的地方 周边:找餐馆.找酒店.找银行.找电影院 在上述应用中,都用到了地图和定位功能,在iOS开发中,要想加入这2大功能,必须基于2个框架进行开发 Map Kit :用于地图展示 Core Location :用于地理定位 2个热门专业术语 LBS :Location Based Service SoLoMo :Social Local Mobile(索罗门)

iOS UI进阶-1.0网易彩票框架搭建

仿网易彩票,最终要做成的效果如下: 一.分层搭建 1.新建一个项目,Lottery.只支持7.1以上坚屏. 2.将素材全部图片全部拉到相应的文件夹里. 3.选中Lottery--右键Show in Finder ,在Lottery文件夹下新建一个Classes,并分别分层成MVC文件夹. 4.把Classes拉到Lottery项目里,整个框架结构如 二.UI搭建 分层好之后,接下来,我们搭建一下界面.使用Storyboard进行搭建. 1.点击Main.storyboard,删除原来的界面,分别

iOS UI进阶-2.0 CALayer

在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮.一个文本标签.一个文本输入框.一个图标等等,这些都是UIView 其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图层.在创建UIView对象时,UIView内部会自动创建一个图层(即CALayer对象),通过UIView的layer属性可以访问这个层 @property(nonatomic,readonly,retain) CALayer *layer; 当UIView需要显示到屏幕上时,会调用drawRect

iOS UI进阶-6.0 手势

在开发过程中,经常会用到,需要关闭某个页面的手势返回功能. // 禁用返回手势 - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]; // 禁用 返回手势 if ([self.navigationController respondsToSelector:@selector(interactivePopGestureRecognizer)]) { self.navigationController.inter

iOS UI进阶-5.0 蓝牙/加速计/传感器

传感器 实现代码: #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 1.开启距离传感器(注意: 默认情况距离传感器是