A.需求
1.超简易画图,只有一种画笔
2.清屏功能
3.回退功能
4.保存功能
5.使用了cocos2D
 
 
 
B.实现方法1
1.基本界面
(1)3个按钮:清屏、回退、保存
(2)绘图view
 
2.画线
(1)使用数组存储绘图点:存储一条线的数组、存储所有线的总数组
(2)在touch的开始、拖曳、结束记录触摸位置,触发重绘
 
3.清屏
删除总数组
 
4.回退
删除最后画的一条线:删除相应数组
 
5.保存到相册
使用”截图”功能,保存绘图view

 //
// PaintView.m
// PaintDemo
//
// Created by hellovoidworld on 15/1/10.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import "PaintView.h"
#import "UIImage+Extension.h" @interface PaintView() @end @implementation PaintView - (NSMutableArray *)lines {
if (nil == _lines) {
_lines = [NSMutableArray array];
}
return _lines;
} #pragma mark - 触摸事件
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint startLocation = [touch locationInView:touch.view]; // 开启一条新的线
NSMutableArray *points = [NSMutableArray array];
// 存储点信息到线上
[points addObject:[NSValue valueWithCGPoint:startLocation]];
// 存储到线组上
[self.lines addObject:points]; // 重绘
[self setNeedsDisplay];
} - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:touch.view]; // 拿到正在画的线
NSMutableArray *points = [self.lines lastObject];
// 添加点信息
[points addObject:[NSValue valueWithCGPoint:location]]; // 重绘
[self setNeedsDisplay];
} - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// 停止拖曳的逻辑其实和拖曳中是一样的
[self touchesMoved:touches withEvent:event];
} #pragma mark - 绘图方法
/** 绘图 */
- (void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext(); // 遍历线组,把所有线画出来
for (NSArray *line in self.lines) {
for (int i=; i<line.count; i++) {
NSValue *pointValue = line[i];
CGPoint point = [pointValue CGPointValue]; // 如果是线的第一个点,要先移动画笔到那个点
if ( == i) {
CGContextMoveToPoint(ctx, point.x, point.y);
} else {
CGContextAddLineToPoint(ctx, point.x, point.y);
}
}
} // 设置线宽、线头样式、线转折样式
CGContextSetLineWidth(ctx, );
CGContextSetLineCap(ctx, kCGLineCapRound);
CGContextSetLineJoin(ctx, kCGLineJoinRound); // 渲染
CGContextStrokePath(ctx);
} #pragma mark - view操作方法
/** 回退 */
- (void)rollback {
[self.lines removeLastObject];
[self setNeedsDisplay];
} /** 清屏 */
- (void)clearScreen {
[self.lines removeAllObjects];
[self setNeedsDisplay];
} /** 保存 */
- (void)save {
// 1.获取图片
UIImage *image = [UIImage imageOfView:self]; // 2.保存图片到相册
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
} /** 保存图片后激发事件
* 这是文档推荐的方法
*/
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
if (error) {
NSLog(@"保存失败");
} else {
NSLog(@"保存成功");
}
} @end
 
 //
// UIImage+Extension.m
// PaintDemo
//
// Created by hellovoidworld on 15/1/11.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import "UIImage+Extension.h" @implementation UIImage(Extension) + (UIImage *) imageOfView:(UIView *) view {
// 1.开启图片上下文
UIGraphicsBeginImageContextWithOptions(view.frame.size, NO, 0.0); // 2.将view的layer渲染到上下文
[view.layer renderInContext:UIGraphicsGetCurrentContext()]; // 3.获取上下文中的图片
UIImage *image = UIGraphicsGetImageFromCurrentImageContext(); // 4.关闭图片上下文
UIGraphicsEndImageContext(); return image;
} @end
 
C.实现方法2
1.基本界面和方法1一样
 
2.画线
(1)使用贝塞尔路径UIBezierPath,一条线就是一个UIBezierPath对象
(2)同样使用数组来存储UIBezierPath对象
 
3.清屏、回退、保存和方法1一样
 
 //
// BezierPaintView.m
// PaintDemo
//
// Created by hellovoidworld on 15/1/11.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import "BezierPaintView.h"
#import "UIImage+Extension.h" @implementation BezierPaintView - (NSMutableArray *)lines {
if (nil == _lines) {
_lines = [NSMutableArray array];
}
return _lines;
} #pragma mark - 触摸事件
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint startLocation = [touch locationInView:touch.view]; // 新建一条Bezier线
UIBezierPath *path = [UIBezierPath bezierPath];
[path setLineWidth:5.0];
[path setLineCapStyle:kCGLineCapRound];
[path setLineJoinStyle:kCGLineJoinRound]; // 移动到始点
[path moveToPoint:startLocation];
// 添加Bezier线到数组
[self.lines addObject:path]; // 重绘
[self setNeedsDisplay];
} - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:touch.view]; // 获得正在画的线
UIBezierPath *path = [self.lines lastObject];
// 画线-添加点信息
[path addLineToPoint:location]; // 重绘
[self setNeedsDisplay];
} - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// 停止拖曳的逻辑其实和拖曳中是一样的
[self touchesMoved:touches withEvent:event];
} #pragma mark - 绘图方法
/** 绘图 */
- (void)drawRect:(CGRect)rect { // 画出所有的线
for (UIBezierPath *path in self.lines) {
// 渲染
[path stroke];
} } #pragma mark - view操作方法
/** 回退 */
- (void)rollback {
[self.lines removeLastObject];
[self setNeedsDisplay];
} /** 清屏 */
- (void)clearScreen {
[self.lines removeAllObjects];
[self setNeedsDisplay];
} /** 保存 */
- (void)save {
// 1.获取图片
UIImage *image = [UIImage imageOfView:self]; // 2.保存图片到相册
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
} /** 保存图片后激发事件
* 这是文档推荐的方法
*/
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
if (error) {
NSLog(@"保存失败");
} else {
NSLog(@"保存成功");
}
} @end
 
 
 
D.附加功能
  • slider控件调整线宽
  • 选择颜色
 
 
1.slider调整线宽
(1)使用slider控件
(2)通过slider的valueChange事件调用方法设置线宽
 
2.选择颜色
(1)创建一个“色块”类
  • 使用UIView作为色块
  • 自定义一个继承UIView的类,作为色块class,给色块UIView加上点击事件
  • 给色块UIView创建一个颜色属性和代理协议,代理是ViewController;创建一个点击代理事件方法
 //
// ColorSelectionView.h
// PaintDemo
//
// Created by hellovoidworld on 15/1/11.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import <UIKit/UIKit.h> @protocol ColorSelectionViewDelegate <NSObject> /** “色块”点击代理方法 */
@optional
- (void) selectColor:(UIColor *) selectedColor; @end @interface ColorSelectionView : UIView /** 代理 */
@property(nonatomic, strong) id<ColorSelectionViewDelegate> delegate; @end //
// ColorSelectionView.m
// PaintDemo
//
// Created by hellovoidworld on 15/1/11.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import "ColorSelectionView.h" @implementation ColorSelectionView - (void)awakeFromNib {
// 给UIView设置点击事件
UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(colorClicked)];
[self addGestureRecognizer:tapGesture];
} /** “色块”点击事件 */
- (void) colorClicked {
[self.delegate selectColor:self.backgroundColor];
} @end
 
(2)自定义一个继承UIBezierPath的类,增加一个线颜色的属性
 //
// HVWBezierPath.h
// PaintDemo
//
// Created by hellovoidworld on 15/1/11.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import <UIKit/UIKit.h> @interface HVWBezierPath : UIBezierPath /** 颜色 */
@property(nonatomic, strong) UIColor *color; @end
 
(3)ViewController代理“色块”的点击事件
  • 拖入所有“色块”对象到ViewController,设置代理
  • 遵守“色块”协议,实现代理方法
 
 //
// ViewController.m
// PaintDemo
//
// Created by hellovoidworld on 15/1/10.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import "ViewController.h"
#import "BezierPaintView.h"
#import "ColorSelectionView.h" @interface ViewController () <ColorSelectionViewDelegate> @property (weak, nonatomic) IBOutlet BezierPaintView *paintView; /** 颜色选择集合 */
@property (strong, nonatomic) IBOutletCollection(ColorSelectionView) NSArray *colorSelection; - (IBAction)rollback;
- (IBAction)clearScreen;
- (IBAction)save;
- (IBAction)lineWidthChange:(UISlider *)sender; @end @implementation ViewController - (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib. // 设置颜色选择器的代理
for (ColorSelectionView *colorView in self.colorSelection) {
colorView.delegate = self;
}
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
} /** 回退 */
- (IBAction)rollback {
[self.paintView rollback];
} /** 清屏 */
- (IBAction)clearScreen {
[self.paintView clearScreen];
} /** 保存 */
- (IBAction)save {
[self.paintView save];
} /** 改变线粗 */
- (IBAction)lineWidthChange:(UISlider *)sender {
self.paintView.lineWidth = sender.value;
} #pragma mark - ColorSelectionViewDelegate 代理方法
- (void) selectColor:(UIColor *) selectedColor {
self.paintView.lineColor = selectedColor;
}

@end

 
(4)“画板”在开始画一条线的时候(触摸开始),设置线宽和颜色
 //
// BezierPaintView.m
// PaintDemo
//
// Created by hellovoidworld on 15/1/11.
// Copyright (c) 2015年 hellovoidworld. All rights reserved.
// #import "BezierPaintView.h"
#import "UIImage+Extension.h"
#import "HVWBezierPath.h" @interface BezierPaintView() @end @implementation BezierPaintView - (NSMutableArray *)lines {
if (nil == _lines) {
_lines = [NSMutableArray array];
}
return _lines;
} #pragma mark - 触摸事件
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint startLocation = [touch locationInView:touch.view]; // 新建一条Bezier线
HVWBezierPath *path = [[HVWBezierPath alloc] init]; // 配置线粗
if (self.lineWidth) {
[path setLineWidth:self.lineWidth];
} // 配置线色
if (self.lineColor) {
path.color = self.lineColor;
} [path setLineCapStyle:kCGLineCapRound];
[path setLineJoinStyle:kCGLineJoinRound]; // 移动到始点
[path moveToPoint:startLocation];
// 添加Bezier线到数组
[self.lines addObject:path]; // 重绘
[self setNeedsDisplay];
} - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint location = [touch locationInView:touch.view]; // 获得正在画的线
HVWBezierPath *path = [self.lines lastObject];
// 画线-添加点信息
[path addLineToPoint:location]; // 重绘
[self setNeedsDisplay];
} - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
// 停止拖曳的逻辑其实和拖曳中是一样的
[self touchesMoved:touches withEvent:event];
} #pragma mark - 绘图方法
/** 绘图 */
- (void)drawRect:(CGRect)rect { // 画出所有的线
for (HVWBezierPath *path in self.lines) { // 设置颜色
if (path.color) {
[path.color set];
} // 渲染
[path stroke];
} } #pragma mark - view操作方法
/** 回退 */
- (void)rollback {
[self.lines removeLastObject];
[self setNeedsDisplay];
} /** 清屏 */
- (void)clearScreen {
[self.lines removeAllObjects];
[self setNeedsDisplay];
} /** 保存 */
- (void)save {
// 1.获取图片
UIImage *image = [UIImage imageOfView:self]; // 2.保存图片到相册
UIImageWriteToSavedPhotosAlbum(image, self, @selector(image:didFinishSavingWithError:contextInfo:), nil);
} /** 保存图片后激发事件
* 这是文档推荐的方法
*/
- (void)image:(UIImage *)image didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo {
if (error) {
NSLog(@"保存失败");
} else {
NSLog(@"保存成功");
}
} @end
 

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

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

    A.需求 1.九宫格手势解锁 2.使用了绘图和手势事件   code source: https://github.com/hellovoidworld/GestureUnlockDemo     B ...

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

    A.需求 1.模仿“网易彩票”做出有5个导航页面和相应功能的Demo 2.v1.0 版本搭建基本框架   code source:https://github.com/hellovoidworld/H ...

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

    A.需要掌握和练习的 1.介绍事件类型2.通过按钮的事件处理引出view的事件处理3.响应者对象 --> UIResponder --> UIView4.view的拖拽* 实现触摸方法,打 ...

  4. iOS UI进阶-4.0 地图与定位

    在移动互联网时代,移动app能解决用户的很多生活琐事,比如 导航:去任意陌生的地方 周边:找餐馆.找酒店.找银行.找电影院   在上述应用中,都用到了地图和定位功能,在iOS开发中,要想加入这2大功能 ...

  5. iOS UI进阶-1.0 Quartz2D

    概述 Quartz 2D是一个二维绘图引擎,同时支持iOS和Mac系统.Quartz 2D能完成的工作: 绘制图形 : 线条\三角形\矩形\圆\弧等 绘制文字 绘制\生成图片(图像) 读取\生成PDF ...

  6. [iOS UI进阶 - 6.0] CALayer

    A.基本知识 1.需要掌握的 CALayer的基本属性 CALayer和UIView的关系 position和anchorPoint的作用   2.概念 在iOS中,你能看得见摸得着的东西基本上都是U ...

  7. iOS UI进阶-3.0 核心动画

    Core Animation是一组非常强大的动画处理API,使用它能做出非常炫丽的动画效果,而且往往是事半功倍,使用它需要先添加QuartzCore.framework和引入对应的框架<Quar ...

  8. iOS UI进阶-2.0 CALayer

    在iOS中,你能看得见摸得着的东西基本上都是UIView,比如一个按钮.一个文本标签.一个文本输入框.一个图标等等,这些都是UIView 其实UIView之所以能显示在屏幕上,完全是因为它内部的一个图 ...

  9. iOS UI进阶-6.0 手势

    给每个页面添加手势,只需要统一设置不是根控制器的页面,都增加手势.需要自定义导航控制器 1.继承代理 @interface BSNavigationController ()<UIGesture ...

随机推荐

  1. linux关机和重启的命令[转]

    如果你很急着关机或者重启话,那么关机就是init 0,重启就是init 6或者reboot Linux中常用的关机和重新启动命令有shutdown.halt.reboot以及init,它们都可以达到关 ...

  2. drop.delete.trauncat的区别

    delete删除数据,保留表结构,可以回滚,如果数据量大,很慢,回滚是因为备份了删除的数据(删除数据时有两个动作,删除和备份) truncate删除所有数据,保留表结构,不可以回滚,一次全部删除所有数 ...

  3. 对于oracle监听器的配置

    oracle 的 net configuration  assist中配置完第一项的监听程序配置(对应文件listener.ora)之后,还要重新配置下第三项本地网络服务名配置(对应文件tnsname ...

  4. Linq 时间对比陷阱坑

    同样的两个datetime 格式的时间     2013年12月2日 17点29分57秒  

  5. busybox filesystem udhcpc 原理

    /******************************************************************** * busybox filesystem udhcpc 原理 ...

  6. cimge 这次能够图片大小尺寸

    CImage imSrc,imDest;imSrc.Load(……);//读入原始图片imDest.Create(……)//创建新大小的图片imSrc.StretchBlt(imDest.GetDC( ...

  7. UVa 11292 The Dragon of Loowater 勇者斗恶龙

    你的王国里有一条n个头的恶龙,你希望雇佣一些骑士把它杀死(也就是砍掉所有的头).村里有m个骑士可以雇佣,一个能力值为 x 的骑士可以砍掉恶龙一个直径不超过 x 的头,且需要支付 x 个金币.如何雇佣骑 ...

  8. poj 2184 Cow Exhibition

    // 给定n头牛,每头有属性智商和幽默感,这两个属性值有正有负,现在要从这n头牛中选出若干头使得他们的智商和与幽默感和不为负数,// 并且两者两家和最大,如果无解输出0,n<=100,-1000 ...

  9. 为在MyEclipse中配置Tomcat服务器郁闷的朋友们解决郁闷

    是不是很郁闷!为了在MyEclipse配置Tomcat 服务器,竟然弄了你几乎一个上午,最后也没弄成功,也许你本该早注意到Tomcat 5.x要有这个JDK的支持,配置才能成功. 一上午辛辛苦苦也没解 ...

  10. [Papers]NSE, $\n u_3$, Lebesgue space, [Pokorny, EJDE, 2003; Zhou, MAA, 2002]

    $$\bex \n u_3\in L^p(0,T;L^q(\bbR^3)),\quad \frac{2}{p}+\frac{3}{q}=\frac{3}{2},\quad 2\leq q\leq \i ...