在这个随笔中,我们要为iPhone实现一个简单的画板App。

首先需要指出的是,这个demo中使用QuarzCore进行绘画,而不是OpenGL。这两个都可以实现类似的功能,区别是OpenGL更快,但是QuarzCore更简单。
第一步,新建Xcode项目,项目名称就叫SimplePaint。
第二步,添加QuarzCore.framework到项目中。
第三步,创建一个新类,类名叫Line。它代表在iPhone的屏幕上绘画时候的线。因为不管是画一条直线还是一条曲线,都可以看做是多条短的直线连接起来的。那么Line需要的是什么属性呢?简单点就是,这条线的开始点和结束点,还有这条线的颜色。所以,打开刚刚创建的Line类,
修改Line.h:
然后修改Line.m:
第四步,接下来创建另一个类,类名叫做ColorPiker。它代表颜色选择器,我们可以点击多个颜色中的一个作为画笔的颜色进行绘画。以下是ColorPiker.h的代码:
aColorPikerIsSelected是一个委托,当当前选择器被选中后,它可以把当前选中的颜色选择器的颜色值传递出去,传递给实现了这个委托的类。在我们的这个demo中,我们会让画板View的实现此委托。
实现ColorPiker.m:
第五步,接下来我们就创建我们的画板View,它代表可以画图的那部分有效区域。创建一个新类叫做TouchDrawView。修改TouchDrawView.h的内容:
刚刚上文中也提过了,我们画图的主要思想就是把多个短线首尾连接起来,就可以成为一条轨迹。所以我们的画板有一个array,它的item就是Line类型,它就是滑过轨迹的所有Line的集合。我们还有一个单独的Line对象,表示在绘画过程中,当前正在画的这条线。另外有一个Color类型的属性,表示线的颜色,也就是用来保存ColorPiker传递出来的颜色值。
实现TouchDrawView.m
  1 //
  2 //  TouchDrawView.m
  3 //  CaplessCoderPaint
  4 //
  5 //  Created by backslash112 on 14/10/29.
  6 //  Copyright (c) 2014年 backslash112. All rights reserved.
  7 //
  8
  9 #import "TouchDrawView.h"
 10 #import "Common.h"
 11
 12 @implementation TouchDrawView
 13 {
 14 }
 15 @synthesize currentLine;
 16 @synthesize linesCompleted;
 17 @synthesize drawColor;
 18
 19 - (id)initWithCoder:(NSCoder *)c
 20 {
 21     self = [super initWithCoder:c];
 22     if (self) {
 23         linesCompleted = [[NSMutableArray alloc] init];
 24         [self setMultipleTouchEnabled:YES];
 25
 26         drawColor = [UIColor blackColor];
 27         [self becomeFirstResponder];
 28     }
 29     return self;
 30 }
 31
 32 //  It is a method of UIView called every time the screen needs a redisplay or refresh.
 33 - (void)drawRect:(CGRect)rect
 34 {
 35     CGContextRef context = UIGraphicsGetCurrentContext();
 36     CGContextSetLineWidth(context, 5.0);
 37     CGContextSetLineCap(context, kCGLineCapRound);
 38     [drawColor set];
 39     for (Line *line in linesCompleted) {
 40         [[line color] set];
 41         CGContextMoveToPoint(context, [line begin].x, [line begin].y);
 42         CGContextAddLineToPoint(context, [line end].x, [line end].y);
 43         CGContextStrokePath(context);
 44     }
 45 }
 46
 47 - (void)undo
 48 {
 49     if ([self.undoManager canUndo]) {
 50         [self.undoManager undo];
 51         [self setNeedsDisplay];
 52     }
 53 }
 54
 55 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
 56 {
 57     [self.undoManager beginUndoGrouping];
 58     for (UITouch *t in touches) {
 59         // Create a line for the value
 60         CGPoint loc = [t locationInView:self];
 61         Line *newLine = [[Line alloc] init];
 62         [newLine setBegin:loc];
 63         [newLine setEnd:loc];
 64         [newLine setColor:drawColor];
 65         currentLine = newLine;
 66     }
 67 }
 68
 69 - (void)addLine:(Line*)line
 70 {
 71     [[self.undoManager prepareWithInvocationTarget:self] removeLine:line];
 72     [linesCompleted addObject:line];
 73 }
 74
 75 - (void)removeLine:(Line*)line
 76 {
 77     if ([linesCompleted containsObject:line])
 78         [linesCompleted removeObject:line];
 79 }
 80
 81 - (void)removeLineByEndPoint:(CGPoint)point
 82 {
 83     NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
 84         Line *evaluatedLine = (Line*)evaluatedObject;
 85         return evaluatedLine.end.x == point.x &&
 86         evaluatedLine.end.y == point.y;
 87     }];
 88     NSArray *result = [linesCompleted filteredArrayUsingPredicate:predicate];
 89     if (result && result.count > 0) {
 90         [linesCompleted removeObject:result[0]];
 91     }
 92 }
 93
 94 - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
 95 {
 96     for (UITouch *t in touches) {
 97         [currentLine setColor:drawColor];
 98         CGPoint loc = [t locationInView:self];
 99         [currentLine setEnd:loc];
100
101         if (currentLine) {
102             [self addLine:currentLine];
103         }
104         Line *newLine = [[Line alloc] init];
105         [newLine setBegin:loc];
106         [newLine setEnd:loc];
107         [newLine setColor:drawColor];
108         currentLine = newLine;
109     }
110     [self setNeedsDisplay];
111 }
112
113 - (void)endTouches:(NSSet *)touches
114 {
115     [self setNeedsDisplay];
116 }
117
118 - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
119 {
120     [self endTouches:touches];
121     [self.undoManager endUndoGrouping];
122 }
123
124 - (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
125 {
126     [self endTouches:touches];
127 }
128
129 - (BOOL)canBecomeFirstResponder
130 {
131     return YES;
132 }
133
134 - (void)didMoveToWindow
135 {
136     [self becomeFirstResponder];
137 }
138
139 - (id)initWithFrame:(CGRect)frame
140 {
141     self = [super initWithFrame:frame];
142     if (self) {
143         // Initialization code
144     }
145     return self;
146 }
147
148 @end

这个文件包含了主要的逻辑,说明下主要方法的作用:

-(id)initWithCoder:当此view被创建的时候这个方法自动调用,所以你不一定必须要实现它;当时当你想在初始化的时候做一些别的工作的时候你就需要实现它。

-(void)drawRect:每次当屏幕需要重新显示或者刷新的时候这个方法会被调用。

-(void)touchBegan:当你的手指点击到屏幕的时候这个方法会被调用。

-(void)touchMove:当你的手指点击屏幕后开始在屏幕移动,它会被调用。随着手指的移动,相关的对象会秩序发送该消息。

-(void)touchEnd:当你的手指点击屏幕之后离开的时候,它会被调用。

还需要讲解下的是,当每次touchMove方法中,往array中添加入了新的Line,要想在画布中显示出来,需要刷新下页面,调用[self setNeedsDisplay]方法即可。
基本的主要逻辑就是这样,我们还差什么?当然是UI!
第六步,创建一个 .xib文件,叫做TouchDrawViewController.xib。在右边的工具箱中添加一个View,再往View中加入多个子View,加多少个你随意,因为这几个子View是用来作为颜色选择器的,多几个少几个无所谓。然后设置这几个子View的Class为 ColorPiker,接着设置他们的背景颜色,颜色值你随意,因为会把被选中的颜色选择器的背景颜色直接作为参数传出来。

我们还需要一个画布的区域,再添加一个View,拉伸它,让它覆盖整个空白区域。同样更改它的Class,改为 TouchDrawView。
 
我们基本快要完成了。
第七步,为刚刚的UI添加一个View Controller类,新建类文件,命名为TouchDrawViewController。修改 .h 文件为:
可以看到它实现了ColorPikerDelegate委托,当ColorPiker 被选中后,色值(背景色)会传递到当前类作为画笔的颜色。
接下来连接UI和ViewController。
同时打开TouchDrawViewController.xib和TouchDrawViewController.h,Ctrl+Drop UI上的每个色块和画布到TouchDrawViewController.h,完成后TouchDrawViewController.h是这样的:
实现TouchDrawViewController.m:
在ViewDidLoad方法中,我们把每个ColorPiker的delegate为self,然后实现aColorPikerIsSelected方法,这样色值就可以传递过来了。
最后,设置TouchrawViewController为rootController。打开delegate.m文件,修改didFinishLaunchingWithOptions方法为:
可以了,运行它吧!

相关源代码:github

转载于:https://www.cnblogs.com/sirkevin/p/4067176.html

在iOS中实现一个简单的画板App相关推荐

  1. 用java的事件监听机制实现一个简单的画板应用:通过选择图形按钮和颜色按钮来画出自己想画的图形:直线、空心矩形、圆形、折线、多边形、圆角矩形、弧线、曲线、喷枪

    今天做一个简单的画板,完整代码附在文章末尾处. - 功能:通过选择图形按钮和颜色按钮来画出自己想画的图形. - 界面展示: - 思路: 1.做一个可视化界面:创建JFrame对象,并设置Title.S ...

  2. Flutter For App——一个简单的豆瓣APP

    一个简单的豆瓣APP 效果视频 功能简述 功能 第三方库 接口简述 底部导航栏 效果图 实现 初始化BottomNavigationBarItem bottomNavigationBar 切换页面导致 ...

  3. Android——一个简单的音乐APP(二)

    一个简单的音乐APP 效果视频 前言 音乐下载 音乐下载效果图 实习步骤&思想 添加到下载队列 单任务下载 多任务下载 音乐下载 获取音乐下载源 创建本地路径 创建目录 开始音乐下载 下载进度 ...

  4. 用Android Studio设计的一个简单的闹钟APP

    该闹钟是用Android Studio为安卓手机设计的一个简单的闹钟APP 一.介绍系统的设计界面 闹钟的布局文件代码如下 <?xml version="1.0" encod ...

  5. 编写一个简单的生日快乐APP

    编写一个简单的生日快乐APP 一.关闭之前的helloworld程序 点击file,然后close project,就完成关闭了. 二.创建一个新的happybirthday程序 三.下面开始整个AP ...

  6. 一个html写的app首页,如何快速开发一个简单好看的APP控制页面

    原标题:如何快速开发一个简单好看的APP控制页面 导读 机智云开源框架为了让开发者快速开发APP,已将用户登录,设备发现,设备配网等功能做成了各个标准模块,仅保留控制页面让开发者自行开发设计,节省了开 ...

  7. Android——一个简单的天气APP

    一个简单的天气APP 效果演示视频 简述 天气JSON数据 实况天气 逐24小时天气预报 未来七天天气预报 天气详情页 效果图 获取JSON数据 URL请求 实况天气URL 逐24小时天气预报URL ...

  8. 『牛角书』HarmonyOS鸿蒙实战 开发一个简单聊天助手APP

    前言 我是通过b站上面老师的讲解,跟着老师编写了一个简单聊天助手app,简答实用,对于刚开始接触鸿蒙的我们来说很有帮助. 创建项目 所用软件为DevEco Studio,点击Create Harmon ...

  9. 使用Android studio做一个简单的网站APP

    1.首先创建一个空白Android项目 2.然后打开项目,切换为Android视图,这时候会看到三个文件夹,分别是manifests.java.res.首先修改res/layout下的activity ...

最新文章

  1. ICLR 2020 九篇满分论文!!!
  2. 最重要的事情只有一件
  3. Activemq -- Spring 整合
  4. Spring Web Flow 入门demo(三)嵌套流程与业务结合 附源码
  5. android官方文档中文版_最全实至名归,NumPy 官方早有中文教程,结合深度学习,还有防脱发指南...
  6. VMware8 8.0.1 安装Lion正式版 原版镜像 直接DMG安装 非整合版 免引导 完美解决iCloud...
  7. RedisCrawlSpider
  8. poj 3177 Redundant Paths(tarjan边双连通)
  9. 【转】Tomcat总体结构(Tomcat源代码阅读系列之二)
  10. 在应用中集成科大讯飞的语音识别技术
  11. 【论文解读】Sort、Deep-Sort多目标跟踪算法
  12. 机智云与汇桔网达成战略合作,进一步完善物联网生态系统
  13. 【luminate primordial】苏州之行
  14. xheditor编辑器的使用
  15. AdSense 使用教程: 通过让 Google 在您的网站上投放广告,帮助您从中获利
  16. php-java-net-python-爱心公益网站()计算机毕业设计程序
  17. 计算机英语期末试题,计算机英语期末考试试题
  18. Chrome 浏览器
  19. 开始尝试贝茨视觉训练法
  20. 繁体中文和简体中文编码

热门文章

  1. C语言显示USDOS汉字库
  2. SQL点滴系列之删除数据(五)
  3. 2-Eighteenth Scrum Meeting-20151218
  4. 同TTX更可爱的层次分析法游戏破解
  5. QT_StepByStep(2)--滑动杆的实现
  6. Rop 文件上传解决思路
  7. android学习一---搭建开发环境
  8. 汉诺塔问题 hdu 2064 hdu1997
  9. Flash of Unstyled Content (FOUC)
  10. HTML-盒子模型(padding-margining)-样式继承-浮动