您的位置:首页 > 移动开发 > IOS开发

ios 实现带矩形框的屏幕截图

2013-07-14 20:06 531 查看
前言:本来只是想实现一个简单的截图功能的,后来又想做的更好一点,就加上了虚线框。要实现截图本身是很容易的,只需要CGImageCreateWithImageInRect:这一个方法即可。后来加了虚线框就复杂了很多,因为还要让虚线框适时的消失。

现附上最终实现的效果:


截图后,点击segControl,虚线框会消失;点击屏幕的任何地方,虚线框和segControl都会消失。除了界面有点丑外,算是基本实现了预期效果。

正文:

我们希望的是:当手指在屏幕上移动时,虚线框随着手指的移动而生成。两个关键问题:手指移动时怎么触发画图机制?怎么绘制虚线框?

一、手指移动的检测

不需要在@interface中继承什么,直接在.m文件中,实现以下几个方法即可。他们都是UIResponder的方法。

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;


当手指开始移动时,系统自动调用touchesBegan; 在手指移动过程中,touchesMoved; 手指移动结束,touchesEnded; 当有外来事件,如打入电话,touchesCancelled。

唯一需要注意的是:这些都是系统自动调用的方法,不需要自己调用!

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"touchesBegan");
_isMoved = false;//在本程序中,设置这个参数的目的是为了让虚线框适时消失
_touch = [[touches anyObject]retain];
startPoint = [_touch locationInView:self];//记录起始点,point是声明为全局变量
[_segControl removeFromSuperview];
[self setNeedsDisplay];   //重绘界面,目的在于让虚线框消失
}

//手指移动过程
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"touchesMoved");
_isMoved = true;
endPoint=[_touch locationInView:self];//记录结束点的坐标

// 用结束点的坐标减去起始点的坐标我么得到一个矩形框的宽和高,声明一个点记录一下;
finalPoint.x=endPoint.x-startPoint.x;
finalPoint.y=endPoint.y-startPoint.y;
// 调用重绘方法,setNeedsDisplay中会自动调用drawRect:,我们不能自己调用drawRect:
[self setNeedsDisplay];
}

-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"touchesEnded");
endPoint = [_touch locationInView:self];//记录起始点,point是声明为全局变量
if(_isMoved){
_segControl.frame = CGRectMake(endPoint.x-50,endPoint.y+5,100,35);
[self addSubview:_segControl];
}
_isMoved = false;
[_touch release];
}

//当接收到系统中断时,这些方法都不是自己调用的
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
NSLog(@"touchesCancelled");
}


二、虚线框的绘制
上面的代码中,我们在两个地方都调用了这样一个方法:[self setNeedsDisplay],这是UIView提供的方法,表示需要开始重绘界面。它还有个类似的,叫setNeedsDisplayInRect,表示在一个矩形区域内重绘界面。

这个方法的具体实现我们是不知道的,但我们知道的是,这个方法会自动调用drawRect:方法,界面重绘的具体操作都是在drawRect:中进行的。

所以,我们要自己绘制界面必须调用setNeedsDisplay方法,并重写drawRect方法。

//准备工作做好后,我们就要画虚线的矩形框了.我们需要重写drawRect方法。完整代码如下:
- (void)drawRect:(CGRect)rect//这个rect参数是这个view在一个cotroller中的位置
{
NSLog(@"drawRect called ,%f %f %f %f",rect.origin.x,rect.origin.y,rect.size.width,rect.size.height);
if(_isMoved == true){
//获取绘图上下文-画板
CGContextRef ref=UIGraphicsGetCurrentContext();
//设置虚线
float lengths[] = {10,10};
CGContextSetLineDash(ref,2, lengths, 1);
//画截取线框
CGContextAddRect(ref,CGRectMake(startPoint.x,startPoint.y,finalPoint.x,finalPoint.y));
//设置颜色
CGContextSetStrokeColorWithColor(ref,[UIColor redColor].CGColor);
//设置线宽
CGContextSetLineWidth(ref,3);
CGContextStrokePath(ref);
}


在touchesMoved中,我将_isMoved设为true,重绘界面时,会画出矩形框;

在touchesEnd中,将_isMoved设为false,那么它调用的重绘界面,就不会画矩形框,实现了矩形框的消失。

三、区域截图

这个实在是没有什么好讲的,直接附代码

//截取图片
-(UIImage *)cutImageFromOrignalImage
{
CGRect rect = CGRectMake(startPoint.x,startPoint.y,finalPoint.x,finalPoint.y);
CGImageRef imgRef = CGImageCreateWithImageInRect([_orignalImage CGImage], rect);
UIImage *img = [UIImage imageWithCGImage:imgRef];
return img;
}


四、特别注意

这个程序也算基本完成了。但是,有一点要注意,那就是这个上面显示的image,是怎么加上去的。

一般情况下,我们都是直接用imageView.image = img,把图片添加进来,但是在这种需要在界面上绘图的情况,这种加图片的方法就不行了,不是加不上去,而是画不上矩形框,必须把这个img设为背景:

self.backgroundColor = [UIColor colorWithPatternImage:_orignalImage];


这个现象很奇怪,手指移动都能检测,也能触发绘图,segcontrol也能显示,但就是画不上矩形框。

分析:在网上查了一下,貌似是drawRect:方法不能在UIImageView上画图。很奇怪哈,UIImageView继承自UIView,为什么不能再上面画图了?苹果官方文档上是这么说的:UIImageView是专门为显示图片做的控件,用了最优显示技术,是不让调用darwrect方法的, 要调用这个方法,只能从UIView里重写。

但我之前猜测以为可能是图层layer问题吧,就查了下,发觉这块也有很多东西应该学习。

可以考虑看一下 CALayer和UIView 这2者的联系和区别,到时候可参考这篇博客http://www.cnblogs.com/lovecode/articles/2249548.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: