首页 > 代码库 > IOS学习笔记 -- Modal和Quartz2D
IOS学习笔记 -- Modal和Quartz2D
一. Modal
1.Modal的默认效果:新控制器从屏幕的最底部往上钻,直到盖住之前的控制器为止;Modal只是改变了View的现实,没有改变rootViewController
2.常用方法
1>.以Modal的形式展示控制器
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^)(void))completion
2>.关闭当初Modal出来的控制器
- (void)dismissViewControllerAnimated: (BOOL)flag completion: (void (^)(void))completion;
3.如果一个控制器是以模态的形式展现出来的, 可以调用该控制器以及该控制器的子控制器让让控制器消失
4.使用场合
1>.如果控制器之间的关系比较紧密一般用UINavigationController
2>.如果控制器之间的关系不是很紧密一般用Modal
二.Quartz2D
1.用途
1>.绘制图形 : 线条\三角形\矩形\圆\弧等
2>.绘制文字
3>.绘制\生成图片(图像)
4>.读取\生成PDF
5>.截图\裁剪图片
6>.自定义UI控件
2.图形上下文
1>.是一个CGContextRef类型的数据
2>.作用:
1).保存绘图信息、绘图状态
2).决定绘制的输出目标(绘制到什么地方去?PDF文件、Bitmap或者显示器的窗口上)
3>.Quartz2D提供了以下几种类型的Graphics Context:
1).Bitmap Graphics Context
2).PDF Graphics Context
3).Window Graphics Context
4).Layer Graphics Context
5).Printer Graphics Context
3.自定义view
1>.如何利用Quartz2D自定义view
首先,得有图形上下文,因为它能保存绘图信息,并且决定着绘制到什么地方去
其次,那个图形上下文必须跟view相关联,才能将内容绘制到view上面
2>.自定义view的步骤
1).新建一个类,继承自UIView
2).实现- (void)drawRect:(CGRect)rect方法,然后在这个方法中
3).取得跟当前view相关联的图形上下文(在drawRect:方法中系统已经自动创建了Layer的图形上下文)
4).绘制相应的图形内容
5).利用图形上下文将绘制的所有内容渲染显示到view上面
4.常用方法
1>.创建图形上下文
UIGraphicsBegin...();
2>.获取图形上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
3>.渲染图形
// 渲染一个空心的图形
CGContextStrokePath(ctx);
// 渲染一个实心的图形
CGContextFillPath(ctx);
4>.关闭路径
CGContextClosePath(ctx);
5>.设置图形颜色
CGContextSetRGBStrokeColor(ctx, 1.0, 0, 0, 1.0);
CGContextSetRGBFillColor(ctx, 1.0, 0, 0, 1.0);
[[UIColor purpleColor] setFill];
[[UIColor blueColor] setStroke];
[[UIColor greenColor] set]; // 推荐使用
6>.图形上下文栈
// 保存一份图形上下文 (需要多少需要还原的图形上下文,就要保存多少次)
CGContextSaveGState(ctx);
// 还原开始保存的那份图形上下文
CGContextRestoreGState(ctx);
7>.指定上下文中可以显示内容的范围
// 注意,指定范围(也就是指点剪切的方法一定要在绘制范围之前调用),可用范围的适用范围是在指定之后,也就说在在指定剪切的范围之前绘制的东西不受影响
CGContextClip(ctx);
8>.矩阵操作
// 注意:设置矩阵操作必须在添加绘图信息之前
CGContextRotateCTM(ctx, M_PI_4);
CGContextScaleCTM(ctx, 0.5, 0.5);
CGContextTranslateCTM(ctx, 0, 150);
9>.获取bigmap制作好的图形
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
5.画线
// 如果是在drawRect方法中调用UIGraphicsGetCurrentContext方法获取出来的就是Layer的上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 设置起点
CGContextMoveToPoint(ctx, 10, 100);
// 设置终点
CGContextAddLineToPoint(ctx, 100, 100);
// 设置线条宽度
CGContextSetLineWidth(ctx, 10);
// 设置线条的起点和终点的样式
CGContextSetLineCap(ctx, kCGLineCapRound);
// 设置线条的转角的样式
CGContextSetLineJoin(ctx, kCGLineJoinRound);
// 绘制一条空心的线,画线只能是空心的
CGContextStrokePath(ctx);
6.画四边形
// 获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 绘制四边形
CGContextAddRect(ctx, CGRectMake(10, 10, 150, 100));
// 渲染图形到layer上
CGContextStrokePath(ctx);
// CGContextFillPath(ctx);
7.画圆和圆弧
// 获取上下文
CGContextRef ctx = UIGraphicsGetCurrentContext();
// 画圆弧
CGContextAddArc(ctx, 100, 100, 50, M_PI_2, M_PI, 0); // 100, 100圆心, 50半径, M_PI_2开始的弧度, M_PI结束的弧度, clockwise 画圆弧的方向 (0 顺时针, 1 逆时针)(按照起点是OC坐标系的情况)
// 画椭圆
CGContextAddEllipseInRect(ctx, CGRectMake(50, 50, 100, 50));
// 画圆
// 第一种
CGContextAddArc(ctx, 100, 100, 50, 0, 2 * M_PI, 0);
// 第二种
CGContextAddEllipseInRect(ctx, CGRectMake(50, 50, 100, 100));
// 渲染图形到layer上
CGContextStrokePath(ctx);
// CGContextFillPath(ctx);
7.画文字
NSString *str = @"天气好";
NSMutableDictionary *md = [NSMutableDictionary dictionary];
// 设置文字颜色
md[NSForegroundColorAttributeName] =[UIColor redColor];
// 设置文字背景颜色
md[NSBackgroundColorAttributeName] = [UIColor greenColor];
// 设置文字大小
md[NSFontAttributeName] = [UIFont systemFontOfSize:20];
// 将文字绘制到指点的位置
// [str drawAtPoint:CGPointMake(10, 10) withAttributes:md];
// 将文字绘制到指定的范围内, 如果一行装不下会自动换行, 当文字超出范围后就不显示
[str drawInRect:CGRectMake(50, 50, 100, 100) withAttributes:nil];
8.画图片
UIImage *image = [UIImage imageNamed:@"bg"];
// 利用OC方法将图片绘制到layer上
// 将图片绘制到指定的位置
// [image drawAtPoint:CGPointMake(0, 0)];
// 利用drawInRect方法绘制图片到layer, 是通过拉伸原有图片
// [image drawInRect:CGRectMake(0, 0, 200, 200)];
// 利用drawAsPatternInRec方法绘制图片到layer, 是通过平铺原有图片
[image drawAsPatternInRect:CGRectMake(0, 0, 320, 480)];
三.触摸事件
iOS中的事件可以分为3大类型
1>.触摸事件
2>.加速计事件
3>.远程控制事件
1.响应者对象
在iOS中不是任何对象都能处理事件,只有继承了UIResponder的对象才能接收并处理事件。我们称之为“响应者对象”
UIApplication、UIViewController、UIView都继承自UIResponder,因此它们都是响应者对象,都能够接收并处理事件
2.UIResponder
UIResponder内部提供了以下方法来处理事件
1>.触摸事件
- (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;
2>.加速计事件
- (void)motionBegan:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionEnded:(UIEventSubtype)motion withEvent:(UIEvent *)event;
- (void)motionCancelled:(UIEventSubtype)motion withEvent:(UIEvent *)event;
3>.远程控制事件
- (void)remoteControlReceivedWithEvent:(UIEvent *)event;
3.UIView的触摸事件处理: 重新UIResponder触摸事件的四个方法
1>.触摸开始:一根或者多根手指开始触摸view,系统会自动调用view的下面方法
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
2>.触摸移动:一根或者多根手指在view上移动,系统会自动调用view的下面方法(随着手指的移动,会持续调用该方法)
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
3>.触摸结束:一根或者多根手指离开view,系统会自动调用view的下面方法
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
4>.触摸取消(可能会经历):触摸结束前,某个系统事件(例如电话呼入)会打断触摸过程,系统会自动调用view的下面方法
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
5>.4个触摸事件处理方法中,都有NSSet *touches(存放的都是UITouch对象)和UIEvent *event两个参数
1).一次完整的触摸过程中,只会产生一个事件对象,4个触摸方法都是同一个event参数
2).如果两根手指同时触摸一个view,那么view只会调用一次touchesBegan:withEvent:方法,touches参数中装着2个UITouch对象
3).如果这两根手指一前一后分开触摸同一个view,那么view会分别调用2次touchesBegan:withEvent:方法,并且每次调用时的touches参数中只包含一个UITouch对象
4).根据touches中UITouch的个数可以判断出是单点触摸还是多点触摸
4.UITouch
1>.当用户用一根手指触摸屏幕时,会创建一个与手指相关联的UITouch对象; 一根手指对应一个UITouch对象;Began:,Moved:和Ended:中一根手指保存的UITouch对象是相同的
2>.作用
1).保存着跟手指相关的信息,比如触摸的位置、时间、阶段
2).当手指移动时,系统会更新同一个UITouch对象,使之能够一直保存该手指在的触摸位置
3).当手指离开屏幕时,系统会销毁相应的UITouch对象
3>.常用属性和方法
1).触摸产生时所处的窗口: @property(nonatomic,readonly,retain) UIWindow *window;
2).触摸产生时所处的视图: @property(nonatomic,readonly,retain) UIView *view;
3).短时间内点按屏幕的次数,可以根据tapCount判断单击、双击或更多的点击: @property(nonatomic,readonly) NSUInteger tapCount; // 注意:移动开发中要避免使用双击或更多的点击事件
4).记录了触摸事件产生或变化时的时间,单位是秒: @property(nonatomic,readonly) NSTimeInterval timestamp;
5).当前触摸事件所处的状态: @property(nonatomic,readonly) UITouchPhase phase;
6).- (CGPoint)locationInView:(UIView *)view; // 返回值表示触摸在view上的位置,这里返回的位置是针对view的坐标系的(以view的左上角为原点(0, 0)),调用时传入的view参数为nil的话,返回的是触摸点在UIWindow的位置
7).- (CGPoint)previousLocationInView:(UIView *)view; // 该方法记录了前一个触摸点的位置
5.UIEvent
1>.每产生一个事件,就会产生一个UIEvent对象; UIEvent:称为事件对象,记录事件产生的时刻和类型
2>.常见属性
1).事件类型: @property(nonatomic,readonly) UIEventType type;
2).事件子类型: @property(nonatomic,readonly) UIEventSubtype subtype;
3).事件产生的时间: @property(nonatomic,readonly) NSTimeInterval timestamp;
6.UIView不接收触摸事件的三种情况
1>.不接收用户交互 userInteractionEnabled = NO
2>.隐藏 hidden = YES
3>.透明 alpha = 0.0 ~ 0.01
提示:UIImageView的userInteractionEnabled默认就是NO,因此UIImageView以及它的子控件默认是不能接收触摸事件的
7.手势识别器----UIGestureRecognizer
1>.UIGestureRecognizer是一个抽象类,定义了所有手势的基本行为,使用它的子类才能处理具体的手势
1).UITapGestureRecognizer(敲击)
2).UIPinchGestureRecognizer(捏合,用于缩放)
3).UIPanGestureRecognizer(拖拽)
4).UISwipeGestureRecognizer(轻扫)
5).UIRotationGestureRecognizer(旋转)
6).UILongPressGestureRecognizer(长按)
2>.UITapGestureRecognizer的使用步骤
1).创建手势识别器对象
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] init];
2).设置手势识别器对象的具体属性
// 连续敲击2次
tap.numberOfTapsRequired = 2;
// 需要2根手指一起敲击
tap.numberOfTouchesRequired = 2;
3).添加手势识别器到对应的view上
[self.iconView addGestureRecognizer:tap];
4).监听手势的触发
[tap addTarget:self action:@selector(tapIconView:)];
3>.手势识别的状态
typedef NS_ENUM(NSInteger, UIGestureRecognizerState) {
// 没有触摸事件发生,所有手势识别的默认状态
UIGestureRecognizerStatePossible,
// 一个手势已经开始但尚未改变或者完成时
UIGestureRecognizerStateBegan,
// 手势状态改变
UIGestureRecognizerStateChanged,
// 手势完成
UIGestureRecognizerStateEnded,
// 手势取消,恢复至Possible状态
UIGestureRecognizerStateCancelled,
// 手势失败,恢复至Possible状态
UIGestureRecognizerStateFailed,
// 识别到手势识别
UIGestureRecognizerStateRecognized = UIGestureRecognizerStateEnded
};