IOS画图
首先说明一下要求,知道了要求之后才能更好地工作呢。
1、通过滑动滑块来修改画笔的粗细;最小值为4,最大值为15;UISlider;
2、点击撤销按钮后,绘图区域撤销上一次画线操作;
3、点击保存按钮后,将绘图区域的图片按照顺序保存到上方的视图中;UIImageView;
4、保存的图片大于6张后,继续从第一个视图按照顺序往下保存;
5、每次点击按钮后,还要将绘制的图片保存到iOS相册内; 可以通过UIImageWriteToPhotosAlbum函数保存到图片相册,保存成功后可以在iPhone模拟器的照片应用程序中查看

首先创建工程,single view Application
先说说思路:
1.将界面给布置好,图片1——6的位置为UIImageView,"撤销"“保存",是两个UIButton,中间是一个UISlider,下面绘图区是一个UIView
2.当点击保存的时候,会弹出对话框,提示是否进行保存,如果保存就将绘图区的图片保存到上面同时保存的本地的照片库中,如果点击取消,则不进行保存
3.写保存,撤销按钮点击事件,(NSLog(@"hello");)进行界面测试
4.对绘图区进行书写,进行绘图。
5.绘图区应该是在外面是一个自己创建的继承与UIView的View
6.在绘图区的操作:
6.1.重写
- (void)drawRect:(CGRect)rect;方法
首先是重写父视图的drawRect:rect方法;
6.2.添加
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;方法
6.3.添加
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;方法
6.4.将每一次画得图保存为一个image,添加方法
- (UIImage *)getImageFromCurrentContext;即得到当前视图的截图
6.5.
画图过程应该是:每一次触摸屏幕的开始,就是一个触摸路径的开始,然后开始绘制,在绘制的过程中,只要绘制就会调用touchesMoved:方法
,同时对图片进行调用[self setNeedsDisplayInrect:rect];程序就会跳转到drawRect:方法中,对图片进行绘制。
根据上面的思路,来进行工作的实施。
首先是界面:
在viewController.m 文件中书写代码:
#import "ViewController.h"
#import "CustomView.h"
#import "CustomManager.h"
#import "CustomPath.h"
@interface ViewController ()
{
NSInteger imageCount;
}
@end
@implementation ViewController
#pragma mark---------------------------------------viewDidLoad
- (void)viewDidLoad
{
[super viewDidLoad];
//后面的白板容器视图
imageCount = 0;
UIView * containerView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
containerView.backgroundColor = [UIColor whiteColor];
containerView.tag = 0;
[self.view addSubview:containerView];
//上面的文字视图
UIView * titleView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 320, 64)];
[containerView addSubview:titleView];
//保存和撤销按钮
UIButton * cancelButton = [[UIButton alloc]initWithFrame:CGRectMake(10, 0, 50, 40)];
[cancelButton setTitle:@"撤销" forState:UIControlStateNormal];
[cancelButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[cancelButton addTarget:self action:@selector(didClickCancelButton:) forControlEvents:UIControlEventTouchUpInside];
cancelButton.backgroundColor = [UIColor grayColor];
UIButton * saveButton = [[UIButton alloc]initWithFrame:CGRectMake(260, 0, 50, 40)];
[saveButton setTitle:@"保存" forState:UIControlStateNormal];
[saveButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[saveButton addTarget:self action:@selector(didClickSaveButton:) forControlEvents:UIControlEventTouchUpInside];
saveButton.backgroundColor = [UIColor grayColor];
[containerView addSubview:cancelButton];
[containerView addSubview:saveButton];
//添加划线空间
UISlider * slider = [[UISlider alloc]initWithFrame:CGRectMake(70, 0, 150, 0)];
[titleView addSubview:slider];
slider.minimumValue = 4.0f;
slider.maximumValue = 15.0f;
[slider addTarget:self action:@selector(changeSliderValue:) forControlEvents:UIControlEventValueChanged];
//添加6个UIImageView
UIView * sixContainerView = [[UIView alloc]initWithFrame:CGRectMake(0, 50, 320, 215)];
sixContainerView.backgroundColor = [UIColor greenColor];
sixContainerView.tag = 3;
[containerView addSubview:sixContainerView];
UIImageView * firstImage = [[UIImageView alloc]initWithFrame:CGRectMake(5, 5, 100, 100)];
UIImageView * secondImage = [[UIImageView alloc]initWithFrame:CGRectMake(110, 5, 100, 100)];
UIImageView * thirdImage = [[UIImageView alloc]initWithFrame:CGRectMake(215, 5, 100, 100)];
UIImageView * forthImage = [[UIImageView alloc]initWithFrame:CGRectMake(5, 110, 100, 100)];
UIImageView * fifthImage = [[UIImageView alloc]initWithFrame:CGRectMake(110, 110, 100, 100)];
UIImageView * sixthImage = [[UIImageView alloc]initWithFrame:CGRectMake(215, 110, 100, 100)];
firstImage.backgroundColor = [UIColor grayColor];
secondImage.backgroundColor = [UIColor grayColor];
[thirdImage setBackgroundColor:[UIColor grayColor]];
forthImage.backgroundColor = [UIColor grayColor];
fifthImage.backgroundColor = [UIColor grayColor];
sixthImage.backgroundColor = [UIColor grayColor];
firstImage.tag = 1001;
secondImage.tag = 1002;
thirdImage .tag = 1003;
forthImage.tag = 1004;
fifthImage .tag = 1005;
sixthImage.tag = 1006;
firstImage.userInteractionEnabled = YES;
secondImage.userInteractionEnabled = YES;
thirdImage.userInteractionEnabled = YES;
forthImage.userInteractionEnabled = YES;
fifthImage.userInteractionEnabled = YES;
sixthImage.userInteractionEnabled = YES;
[firstImage clearsContextBeforeDrawing];
[sixContainerView addSubview:firstImage];
[sixContainerView addSubview:secondImage];
[sixContainerView addSubview:thirdImage];
[sixContainerView addSubview:forthImage];
[sixContainerView addSubview:fifthImage];
[sixContainerView addSubview: sixthImage];
//添加颜色选择
UIButton * redButton = [[UIButton alloc]initWithFrame:CGRectMake(30, 270, 25, 10)];
redButton.backgroundColor = [UIColor redColor];
[redButton addTarget:self action:@selector(didClickRedButton:) forControlEvents:UIControlEventTouchUpInside];
UIButton * greenButton = [[UIButton alloc]initWithFrame:CGRectMake(150, 270, 25, 10)];
[greenButton setBackgroundColor:[UIColor greenColor]];
[greenButton addTarget:self action:@selector(didClickGreenButton:) forControlEvents:UIControlEventTouchUpInside];
UIButton * blueButton = [[UIButton alloc]initWithFrame:CGRectMake(260, 270, 25, 10)];
blueButton.backgroundColor = [UIColor blueColor];
[blueButton addTarget:self action:@selector(didClickBlueButton:) forControlEvents:UIControlEventTouchUpInside];
[containerView addSubview:redButton];
[containerView addSubview:greenButton];
[containerView addSubview:blueButton];
//添加画板视图
CustomView * cView = [[CustomView alloc]initWithFrame:CGRectMake(5, 280, 310, 210)];
cView.backgroundColor= [UIColor grayColor];
cView.tag = 1;
[containerView addSubview:cView];
}
当点击保存按钮和撤销按钮,进行相应地事件的触发,当跳出一个提示框后进行的操作:
#pragma mark---------------------------------------alertView
- (void)alertView:(UIAlertView *)alertViewt clickedButtonAtIndex:(NSInteger)buttonIndex
{
UIView * containerView = [self.view viewWithTag:0];
CustomView * cView = (CustomView *) [containerView viewWithTag:1];
NSMutableArray * pathListArray = [CustomManager defaultManager].pathList;
UIView * sixContainerView = [containerView viewWithTag:3];
NSArray * array = [sixContainerView subviews];
UIImage * tempImage = [cView getImageFromCurrentContext];
switch (buttonIndex) {
case 0:
{
[pathListArray removeAllObjects];
[cView setNeedsDisplay];
}
NSLog(@"取消");
break;
case 1:
{
UIImageWriteToSavedPhotosAlbum(tempImage, NULL, NULL, NULL);
imageCount++;
switch (imageCount) {
case 1:
((UIImageView *)array[0]).image = tempImage;
break;
case 2:
((UIImageView *)array[1]).image = tempImage;
break;
case 3:
((UIImageView *)array[2]).image = tempImage;
break;
case 4:
((UIImageView *)array[3]).image = tempImage;
break;
case 5:
((UIImageView *)array[4]).image = tempImage;
break;
case 6:
((UIImageView *)array[5]).image = tempImage;
break;
default:
break;
}
[pathListArray removeAllObjects];
[cView setNeedsDisplay];
}
NSLog(@"确定");
break;
}
}
#pragma mark---------------------------------------changeSliderValue:
- (void) changeSliderValue:(UISlider *)sender
{
UIView * containerView = [self.view viewWithTag:0];
CustomView * cView = (CustomView *)[containerView viewWithTag:1];
cView.lineWidth = sender.value;
NSLog(@"%f",sender.value);
}
#pragma mark---------------------------------------didClickSaveButton:
- (void) didClickSaveButton:(UIButton *)sender
{
if (imageCount > 5) {
imageCount = 0;
}
UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"是否保存" message:@"要保存吗?" delegate:self cancelButtonTitle:@"取消" otherButtonTitles:@"确定", nil];
[alert show];
NSLog(@"save click");
}
#pragma mark---------------------------------------didClickCancelButton:
- (void) didClickCancelButton:(UIButton *)sender
{
UIView * containerView = [self.view viewWithTag:0];
CustomView * cView = (CustomView *) [containerView viewWithTag:1];
NSMutableArray * pathListArray = [CustomManager defaultManager].pathList;
[pathListArray removeLastObject];
[cView setNeedsDisplay];
NSLog(@"cancel click");
}
#pragma mark---------------------------------------didClickBlueButton:
- (void) didClickBlueButton:(UIButton *)sender
{
UIView * containerView = [self.view viewWithTag:0];
CustomView * cView = (CustomView *) [containerView viewWithTag:1];
cView.lineColor = [UIColor blueColor];
NSLog(@"blue");
}
#pragma mark---------------------------------------didClickRedButton:
- (void) didClickRedButton:(UIButton *)sender
{
UIView * containerView = [self.view viewWithTag:0];
CustomView * cView = (CustomView *) [containerView viewWithTag:1];
cView.lineColor = [UIColor redColor];
NSLog(@"red");
}
#pragma mark---------------------------------------didClickGreenButton:
- (void) didClickGreenButton:(UIButton *)sender
{
UIView * containerView = [self.view viewWithTag:0];
CustomView * cView = (CustomView *) [containerView viewWithTag:1];
cView.lineColor = [UIColor greenColor];
NSLog(@"green");
}
#pragma mark---------------------------------------didReceiveMemoryWarning
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
@end
创建一个单例:用来存储每一条路径的信息。一个数组。这个数组中得元素是一个另外一个类的每一个对象,另外一个类是linpath类。
在这个类中保存着每一个对象的所有数据,(线的路径,线的宽度,线的颜色)。
然后再drawRect:方法中for (in)这个单例中那个数组的所有元素,遍历出后,进行绘画和渲染。
在这里,我们分别实现各个方法,
首先创建一个CustomView,用来进行绘图:绘图代码:
首先是CustomView.h文件中得声明:
#import <UIKit/UIKit.h> @interface CustomView : UIView @property (nonatomic,retain) UIColor* lineColor; - (CGMutablePathRef) pathFromPoint:(CGPoint)originPoint toPoint:(CGPoint) finalPoint; - (UIImage *)getImageFromCurrentContext; @property (nonatomic,assign)float lineWidth; @end
然后是CustomView.m文件中各个方法的实现。
#import "CustomView.h"
#import "CustomManager.h"
#import "CustomPath.h"
//添加自定义视图的延展...
@interface CustomView ()
//获取坐标内的路径...
//- (CGMutablePathRef) pathFromPoint:(CGPoint)originPoint toPoint:(CGPoint) finalPoint;
//- (UIImage *)getImageFromCurrentContext;
@end
//静态内联函数
//程序启动后,这种类型的函数就已经准备完毕,在代码区准备程序内调用
static inline CGPoint midPoint(CGPoint point1,CGPoint point2)
{
CGFloat minX = (point1.x + point2.x)/2.0f;
CGFloat minY = (point2.y + point2.y)/2.0f;
return CGPointMake(minX, minY);
}
@implementation CustomView
{
//添加私有地实例变量
//启动点...
CGPoint startPoint;
//结束点...
CGPoint endPoint;
//控制点
CGPoint controlPoint;
UIImage *tempImage;
//声明路径私有地中间变量
CGMutablePathRef tempPath;
//声明每一次触摸完成后的路径
CGMutablePathRef touchPath;
//声明全部路径变量,用来存储所有的中间路径.....
CGMutablePathRef totalPath;
}
#pragma mark---------------------------------------初始化
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
startPoint = CGPointZero;
endPoint = CGPointZero;
controlPoint = CGPointZero;
//创建全部路径对象存储空间
// totalPath = CGPathCreateMutable();
_lineColor = [UIColor whiteColor];
}
return self;
}
#pragma mark---------------------------------------开始画 drawRect:
- (void)drawRect:(CGRect)rect
{
//通知父类,开始画图....
[super drawRect:rect];
//如果两个都是(0,0),则不画图...
if (CGPointEqualToPoint(startPoint, CGPointZero) && CGPointEqualToPoint(endPoint,CGPointZero)) {
return;
}
//1.获取当前画布...
CGContextRef context = UIGraphicsGetCurrentContext();//context 就是传过来的rect
NSMutableArray * pathListArray = [CustomManager defaultManager].pathList;
for (CustomPath * itemPath in pathListArray) {
CGContextSetLineCap(context, kCGLineCapRound);
CGContextSetLineWidth(context, itemPath.lineWidth);
CGContextSetStrokeColorWithColor(context, itemPath.lineColor);
CGContextAddPath(context, itemPath.linePath);
CGContextStrokePath(context);
}
/**/
//1.开始创建图片画布
/**/
}
#pragma mark---------------------------------------touchBegan
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//每一次触摸屏幕的开始,就是一个触摸路径的开始.....
touchPath = CGPathCreateMutable();
CustomPath * itemPath = [[CustomPath alloc]init];
itemPath.lineWidth =_lineWidth;
itemPath .lineColor = _lineColor.CGColor;
itemPath.linePath = touchPath;
[[CustomManager defaultManager].pathList addObject:itemPath];
//获取触摸对象
UITouch * touch = [touches anyObject];
//设置每次触摸的点
startPoint = [touch previousLocationInView:self];
endPoint = [touch previousLocationInView:self];
controlPoint =[touch previousLocationInView:self];
[self touchesMoved:touches withEvent:event];
}
#pragma mark---------------------------------------touchesMoved
//当手指开始触摸得时候,实现的方法...
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
//获取当前的触摸对象
UITouch * touch = [touches anyObject];
//设置起点
startPoint = controlPoint;
//设置控制点为前一个触摸点
controlPoint = [touch previousLocationInView:self];
//设置中点为当前触摸点
endPoint = [touch locationInView:self];
//生成截图图片对象...
// tempImage = [self getImageFromCurrentContext];
CGPoint mid1 = midPoint(startPoint,controlPoint);
CGPoint mid2 = midPoint(controlPoint, endPoint);
//获取当前应该绘制的路径
tempPath = [self pathFromPoint:mid1 toPoint:mid2];
//获取最小的能够容纳路径的矩形体积
CGRect rect = CGPathGetBoundingBox(tempPath);
rect.origin.x -=15.0f;
rect.origin.y -=15.0f;
rect.size.height +=30.0f;
rect.size.width +=30.0f;
//将中间变量tempPath添加到全部路径
// CGPathAddPath(totalPath, NULL, tempPath);
//将中间变量tempPath添加到每一个的触摸路径touchPath内
CGPathAddPath(touchPath, NULL, tempPath);
//修改最后的自定义的path对象
CustomPath * itemPath = [[CustomManager defaultManager].pathList lastObject];
itemPath.linePath = touchPath;
//这里的self是实例对象
[self setNeedsDisplayInRect:rect];
}
#pragma mark---------------------------------------touchesEnded
//当手指结束触摸时,触发的方法
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
CustomPath * itemPath = [[CustomPath alloc]init];
itemPath.linePath = touchPath;
}
//获取当前视图的截图....
#pragma mark---------------------------------------画图
- (UIImage *)getImageFromCurrentContext
{
//1.开始创建图片画布
UIGraphicsBeginImageContext(self.bounds.size);
//2.将视图的内容渲染到图片画布上
[self.layer renderInContext:UIGraphicsGetCurrentContext()];
//3.通过图片画布获取当前画布...
UIImage *result = UIGraphicsGetImageFromCurrentImageContext();
//4.结束图片画布
UIGraphicsEndImageContext();
return result;
}
#pragma mark---------------------------------------获取坐标内路径
//获取坐标内的路径...
- (CGMutablePathRef) pathFromPoint:(CGPoint)originPoint toPoint:(CGPoint) finalPoint
{
//创建块
CGMutablePathRef path = CGPathCreateMutable();
//移动到出发点
CGPathMoveToPoint(path, NULL, originPoint.x, originPoint.y);
//添加直线结束点
// CGPathAddLineToPoint(path,NULL , finalPoint.x, finalPoint.y);
//添加曲线,通过控制点,到结束点
CGPathAddQuadCurveToPoint(path, NULL, controlPoint.x, controlPoint.y, finalPoint.x, finalPoint.y);
//CGPathRef,CGContextRef,CGColorRef
//的基本类型都是CFtypeRef类型的
//而ARC不支持此类型的自动释放
//将cgpathref对象添加到自动释放池
CFAutorelease(path);
//将路径返回
return path ;
}
@end
附件:
该程序的例子:

文件存到网盘了。百度网盘。

浙公网安备 33010602011771号