一、屏幕适配(autoLayout+sizeClass)

 

1.目前市面上的主流布局形式:

 

a. frame 布局,通过代码计算(老程序员习惯使用)

 

b. autoLayout(新的出现)与sizeClass的结合使用,完美的解决了不同尺寸屏幕横竖屏的问题

 

 

2.autoLayout的核心概念

a.参照

b.约束

 

autoLayout的警告和错误

 

警告:控件的当前的frame,与约束设置的不匹配,就会导致错误,比如:约束空间的高度为200,但控件当前的高度为300,类似这种就会给出解决方案

 

 

错误:

a.缺乏必要的约束;比如:只约束了宽度和高度,没有约束具体的位置。

b.两个约束冲突,;比如:其中一个约束约束了高度为200,另一个高度却约束的为300

 

 

使用代码完成约束

 

添加约束时候的规则:

1.如果添加的约束和其他控件没有关系,会添加到自己身上(比如:设置一个视图的宽,高)

2.如果是父子关系,设置子控件的约束,约束会添加到父控件上

3.两个控件是兄弟关系,约束会添加到两个兄弟控件第一个共同的父控件上

 

     (类似于树状图)

 

使用代码实现为控件添加约束

1.创建NSLayoutConstraint对象

2.给指定的控件添加约束

-(void)addConstraint:(NSLayoutConstraint *)contraint

-(void)addConstraints:(NSArray*)constraints;

 

注意事项:

1.禁用autoresizing功能

2.将view.translatesAutoresizingMaskIntoConstraints = NO;

3.不用在给view设置frame

 

 

 

3.如何使用autoLayout进行页面布局

 

实例1.设置一个宽度150,高度50的view,该视图始终显示在屏幕的正中心(水平居中对齐,垂直居中对齐)。

a.使用原生代码实现约束,

 

 

b.使用第三方库完成约束

 

 

Masonry使用注意事项:

mas_makeConstraints 是给view添加约束,约束有几种,分别是边距,宽,高,左上右下距离,基准线。添加过约束后可以有修正,修正有offset(位移)修正和multipliedBy(倍率)修正。

make.lessThanOrEqualTo + 倍数和位移修正。

[self.view addSubview:view];

equalTo。特别是多个属性时,必须使用equalTo,例如 make.left.and.right.equalTo(self.view);

注意点3: 注意到方法with和and,这连个方法其实没有做任何操作,方法只是返回对象本身,这这个方法的左右完全是为了方法写的时候的可读性 。make.left.and.right.equalTo(self.view);和make.left.right.equalTo(self.view);是完全一样的,但是明显的加了and方法的语句可读性 更好点。

例如:

make.bottom.mas_equalTo(self.view3.mas_top).with.offset(-10);
 
     make.width.and.height.equalTo(self.view3);
 
 make.width.and.height.equalTo(self.view3).multipliedBy(1.5)

 

sizeClass:横屏图片的设置

 

 

 

 

 

 

二、绘图

 

 

【CALayer简介】

 

1.Core Animation是跨平台的,支持iOS环境和Mac OS X环境(Core Service)

2.学习核心动画之前,需要先理解CALayer,因为核心动画操作的对象不是UIView,而是CALayer

3.CALayer是核心动画的基础,可以做圆角、阴影、边框等效果

4.每个UIView内部有一个Layer的属性

5.在实现核心动画时,本质上是将CALayer中的内容转换成那个位图,从而便于图形硬件的操纵

 

ARC机制不适用于CoreService框架的对象

 

(UIView与CALayer的最大区别:CALayer不可以响应交互事件(可以展示内容,可以渲染核心动画))

 

【UIView的CALayer基本演练】

 

1.演练设置UIIMageView中的CALayer属性

—   圆角、边框、阴影以及3D形变属性(transform:其中包括:旋转、缩放、平移)

 

【圆角核心代码】
 //圆弧设置
 imageView.layer.cornerRadius = 100.0f;
 //让子layer自动适配(该值默认为NO,NO的时候,cornerRadius设置无效)
 [imageView.layer setMasksToBounds:YES];
      【圆角核心代码】
 注意:如果maskToBounds为YES时,设置阴影无效
 //设置阴影颜色
 [imageView.layer setShadowColor:[UIColor whiteColor].CGColor];
 //设置阴影偏移量
 [imageView.layer setShadowOffset:CGSizeMake(10.0, 10.0)];
 //设置阴影透明度
 [imageView.layer setShadowOpacity:0.3];
             
            【设置边框核心代码】
 注意:边框会随着layer的形状改变而改变
 //设置边框颜色(注意要使用CGColor)
 [imageView.layer setBorderColor:[UIColor blueColor].CGColor];
 //设置边框的宽度
 [imageView.layer setBorderWidth:3.0f];
 
            【设置3D形变】
 // 1> 平移属性(向上移动100个点)
 [imageView.layer setTransform:CATransform3DMakeTranslation(0, -100, 0)];
 // 2> 缩放属性
 [imageView.layer setTransform:CATransform3DMakeScale(1.0, 1.0, 1.0)];
 // 3> 旋转属性
 // 提示:通常在旋转时指定z轴即可,要延哪个轴旋转,指定一个数值1.0即可
 // 图像本身没有厚度,如果按照x或y旋转90度,图像是不可见的。
 [imageView.layer setTransform:CATransform3DMakeRotation(M_PI_2, 0, 0, 1.0)];

 

2.注意:

—  在UIView中CALayer只是一个类声明,因此需要添加QuartzCore框架

 

颜色时,不能直接使用UIColor,而是需要将UIColor转换成CGColor

 

—  修改图层相当于修改UIView属性,即修改了界面属性

 

—  形变属性既可以用形变函数指定,也可以用keyPath指定(keyPath不做验证)

 

 

【x、y、z坐标系】

 

 

 

【图层和视图之间的关系】

1.创建视图对象时,视图会自己创建一个层,视图在绘图(如drawRect:)时,会将内容画在自己的层上。当视图在层上完成绘图后,系统会将图层拷贝至屏幕。每个视图都有一个层,而每个图层又可以有多个子图层

 

提示:

1> Layer的设计目的不是为了取代视图,因此不能基于CALayer常见一个独立的可视化组件

2> Layer的设计目的是提供视图的基本可视内容,从而提高动画的执行效率

响应者链中。

 

【CALayer层次结构图】

 

 

 

 

【CALayer的使用】

    层(使用CALayer的addSubLayer)

2. 获取到当前图层或者使用静态方法layer初始化CALayer后,可以设置一下基本属性

 

3.  bounds :宽度和高度

    position :   位置(默认指中心点,具体由anchorPoint决定,anchorPoint默认(0.5,0.5))

    anchorPoint:锚点(x,y的范围都是0~1,决定了position的意义)

    backgroundColor :背景色(CGColorRef 类型)

    borderColor :边框颜色(CGColorRef类型)

    borderWidth :边框宽度

    borderRadius :圆角半径

    contents :内容(比如设置为图片  CGImageRef)(一般用来设置图片)

 

注意: 虽然CALayer可以使用frame,但最好还是使用bounds和position

在设置动画时,使用这两者会比较方便

 

【练习】 创建自定义图层演示

使用CALayer的layer方法创建实例

设置以上基本属性

使用addSubLayer方法添加到self.view.layer中

 

【position与achorPoint】

 

 

 

 

【基本绘图的类型】

CGContextRef context = UIGraphicsGetCurrentContext(); //设置上下文
 
 //画一条直线
 CGContextSetStrokeColorWithColor(context, [UIColor redColor].CGColor);//线条颜色
 CGContextSetLineWidth(context, 5.0);//线条宽度
 CGContextMoveToPoint(context, 20, 20); //开始画线, x,y 为开始点的坐标
 CGContextAddLineToPoint(context, 300, 20);//画直线, x,y 为线条结束点的坐标
 CGContextStrokePath(context); //开始画线
 
 
   //绘制连续的曲线
 CGContextSetLineWidth(context, 5.0);
 CGContextSetStrokeColorWithColor(context, [UIColor greenColor].CGColor);
 CGContextMoveToPoint(context, 230, 150);//开始画线, x,y 为开始点的坐标
 CGContextAddCurveToPoint(context, 310, 100, 300, 200, 220, 220);//画三次点曲线
 CGContextAddCurveToPoint(context, 290, 140, 280, 180, 240, 190);//画三次点曲线
 CGContextStrokePath(context);//开始画线
 
 //画一个方形图形 没有边框
 CGContextSetRGBFillColor(context, 0, 0.25, 0, 0.5); //方框的填充色
 CGContextFillRect(context, CGRectMake(5, 150, 100, 100)); //画一个方框
 
 //画方形边框
 CGContextRef context5 = UIGraphicsGetCurrentContext(); //设置上下文
 CGContextSetLineWidth(context5, 3.0);
 CGContextSetRGBStrokeColor(context5, 0.8, 0.1, 0.8, 1);
 CGContextStrokeRect(context5, CGRectMake(5, 5, 300, 400));//画方形边框, 参数2:方形的坐标。
    
    //画弧线
 CGContextSetRGBStrokeColor(context, 0.3, 0.4, 0.5, 1);//线条颜色
 CGContextAddArc(context, 180, 200, 50, 0, 180*(M_PI/180), 0);
   
 CGContextStrokePath(context);//开始画线
 
 
 //画椭圆
 CGRect aRect= CGRectMake(80, 80, 160, 100);
 CGContextSetRGBStrokeColor(context, 0.6, 0.9, 0, 1.0);
 CGContextSetLineWidth(context, 3.0);
 CGContextAddEllipseInRect(context, aRect); //椭圆, 参数2:椭圆的坐标。
 CGContextDrawPath(context, kCGPathStroke);
 
    //画实心圆
     CGContextFillEllipseInRect(context, CGRectMake(95, 195, 200.0, 100));//画实心圆,参数2:圆坐标。可以是椭圆
 
 
 //扇形图的绘制
 
 CGContextRef context = UIGraphicsGetCurrentContext();
    CGPoint center = CGPointMake(150, 150);
    CGFloat radius = 50;
    CGContextMoveToPoint(context, center.x, center.y);
    CGContextAddArc(context, center.x, center.y, radius, 0, M_PI_4, 0);
    CGContextSetFillColorWithColor(context, [UIColor redColor].CGColor);
    CGContextFillPath(context);
    CGContextMoveToPoint(context, center.x, center.y);
    CGContextSetFillColorWithColor(context, [UIColor blueColor].CGColor);
    CGContextAddArc(context, center.x, center.y, radius, M_PI_4, M_PI_2, 0);
    CGContextFillPath(context);
 
 
 
 //柱状图的绘制
 CGContextRef context1 = UIGraphicsGetCurrentContext();
 //绘制x轴
 CGContextMoveToPoint(context1, 20, 280);
 CGContextSetLineWidth(context1, 1);
 CGContextAddLineToPoint(context1, 20, 20);
 CGContextStrokePath(context1);
 //绘制y轴
 CGContextMoveToPoint(context1, 19, 280);
 CGContextAddLineToPoint(context1, CGRectGetWidth(self.frame)-40, 280);
 CGContextStrokePath(context1);
 //柱状图使用绘制矩形的方法绘制
 CGContextFillRect(context1, CGRectMake(30, 80, 50, 200));
 CGContextSetFillColorWithColor(context1, [UIColor redColor].CGColor);
 CGContextFillRect(context1, CGRectMake(80, 30, 50, 250));

 

 

简单画板的制作

- (void)pan:(UIPanGestureRecognizer *)pan{
    CGPoint point = [pan locationInView:self];
    if (pan.state == UIGestureRecognizerStateBegan) {
        _path = [UIBezierPath bezierPath];
        [_path moveToPoint:point];
        [self.array addObject:_path];
    }
    [_path addLineToPoint:point];
    [self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect{
    for (UIBezierPath *path in self.array){
        [path stroke];
    }
}

 

 

 

 

 

 

 

 

 

三、核心动画

 

 

【核心动画】

往事半功倍

 

<QuartzCore/QuartzCore.h>

 

3.开发基本步奏

1、创建一个动画(CAAnimation)对象,设置一些动画相关属性

Properties)

3、添加动画对象到层(CALayer)中,开始执行动画

4、通过调用CALayer的addAnimation:forKey增加动画到层(CALayer)中,这样就可以触发动画了。通过removeAnimationForKey可以停止层中的动画

5、Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程

 

【CAAnimation的继承结构】【CAAnimation—>遵守CAMediaTiming协议(属性来源)】

 

【CAPropertyAnimation 】(两个子类basic,keyframe,抽象类)              【CATransition】

 

【CABasicAnimation】【CAKeyframeAnimation】

 

 

 

 

【CAAnimation简介】

使用它的子类

 

2.常用属性

CFTimeInterval duration

动画的持续时间

 

float repeatCount:

动画重复次数,无限循环可以设置HUGE_VALF或者MAXFLOAT

 

开始之前或者动画结束之后

 

fillMode为kCAFillModeForwards

 

 

    CFTimeInterval   beginTime:

    可以用来设置动画延迟执行时间,若想延迟2s,就设置为CACurrentMediaTime()+2,CACurrentMediaTime()为图层的当前时间

 

   CAMediaTimingFunction *timingFunction:

   速度控制函数,控制动画运行的节奏

 

   id  delegate:

    动画代理

 

【CAAnimation—动画填充方式】

1.filleMode属性值(要想fillMode有效,最好设置removedOncompletion = NO)

2.kCAFillModeRemoved,这个是默认值,也就是说动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态

3.kCAFillModeForwards ,当动画结束后,layer一直保持着动画最后的状态

4.kCAFillModeBackwards,当动画结束前,只需要将动画加入一个layer,layer便立即进入动画的初始状态并等待动画开始

5.kCAFillModeBoth,这个其实就是上边两个的合成,动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持最后的状态

【CAAnimation—速度控制函数】

速度控制函数(CAMediatimingFunction)

1.kCAMediatimingFunctionLiner(线性):匀速,给你一个相对静止的感觉

2.kCAMediatimingFunctionEasyIn(渐进):动画缓慢进入然后加速离开

3.kCAMediatimingFunctionEasyOut(渐出):动画全速进入,然后减速到达目的地

4.kCAMediatimingFunctionEasyInEasyOut(渐进渐出):动画缓慢进入,中间加速,然后减速到达目的地(这是动画默认的行为)

【CAAnimation—动画代理方法】

CAAnimation在分类中定义了代理方法

@interface NSObject (CAAnimationDelegate)
 
 /* Called when the animation begins its active duration. */
 
 - (void)animationDidStart:(CAAnimation *)anim;
 
 /* Called when the animation either completes its active duration or
 * is removed from the object it is attached to (i.e. the layer). 'flag'
 * is true if the animation reached the end of its active duration
 * without being removed. */
 
 - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag;
 
 @end

 

 

【CABasicAnimation】— 基本动画

1.基本动画是CAPropertyAnimation的子类

 

2.属性说明:

keyPath对应属性的初始值

keyPath对应属性的结束值

 

3.动画过程的说明:

1、随着动画的进行,在长度为duration的持续时间内,keyPath对应的属性的值从fromValue渐渐地变为toValue;

2、keyPath对应的属性是CALayer的可动画属性

初始值,并没有真正被改变。

 

【基本动画演练】

演练内容 — 基本动画的实现

 

1.自定义视图

2.平移动画

3.旋转动画

4.缩放动画

 

简单的动画演练可以使用UIView的防射变换来实现

 

程序进入后台后,动画默认停止

#pragma mark 旋转动画
 - (void)rotationAnimation
 {
 // 1. 实例化基本动画
 // 默认按照z轴旋转
 CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
 [self.myView.layer setAnchorPoint:CGPointMake(0, 0)];
 // 2. 设置动画属性
 // 不停的旋转
 // 1) 旋转一周
 [anim setToValue:@(2 * M_PI)];
 // 2) 不停的旋转 - 动画循环播放
 // HUGE_VALF 是一个非常大得浮点数,指定此数值可以认为动画无限循环
 // MAXFLOAT 
 [anim setRepeatCount:HUGE_VALF];
 [anim setDuration:0.5f];
 // 3) 动画完成时删除
 // 对于循环播放的动画效果,一定要将removedOnCompletion设置为NO,否则无法恢复动画
 [anim setRemovedOnCompletion:NO];
 // 3. 添加动画
 // key可以随便指定,用于判断图层中是否存在该动画
 [self.myView.layer addAnimation:anim forKey:@"rotationAnim"];
 }

 

【CAPropertyAnimation】

1.是CAAnimation的子类,也是一个抽象类,要想创建动画对象,应该使用它的两个子类

— CABasicAnimation

— CAKeyframeAnimation

 

属性说明:

— keyPath:通过指定CALayer的一个属性名为keyPath(NSString类型),并且对CALayer的这个属性值进行修改,达到动画效果。

比如:指定keyPath为@“position”,就修改CALayer的position属性值,以达到平移的效果

 

 

【关键帧动画—  CAKeyframeAnimation】

1.关键帧动画,也是CAPropertyAnimation的子类,与CABasicAnimation的区别是:

— CABasicAnimation只能从一个数值(fromValue)到另外一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值

 

2.属性说明:

values:

上边提高的NSArray对象。数组内的元素被称为“关键帧”(keyframe)。动画会在规定的时间(duration)内,依次显示values数组中的每一帧。

 

path:

可以设置一个CGPathRef,让图层按照路径轨迹移动。path只对图层的position跟anchorPoint起作用,如果设置了path,那么values将被忽略。

 

keyTimes:

可以为对应的关键帧设置时间点,其取值范围为0~1,keyTimes中的每一个时间值都对应values中的每一帧。如果没有设置keyTimes,各个关键帧的时间是平分的。

 

3.CABasicAnimation可以看做是只有两个关键帧的CAKeyframeAnimaiton

 

 

【关键帧动画演练】

1、摇晃动画

【核心代码】

- (void)shakeAnimation{
 //晃动动画修改的是layer的rotation
 CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation"];
 //设置晃动角度
 CGFloat angle = M_PI_4 / 10;
 //用来设置每帧动画
 NSArray *values = @[@(angle),@(-angle),@(angle)];
 anim.values = values;
 //设置每帧动画时间
 anim.duration = 0.1;
 //设置重复执行次数
 anim.repeatCount = MAXFLOAT;
 //给图层添加动画
 [self.layer addAnimation:anim forKey:@"shake"];
 }

2、指定多点路径平移动画

- (void)moveToPoint:(CGPoint)point withDuration:(CFTimeInterval)duration withPointCount:(NSInteger)points{
 //创建帧动画
 CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
 //设置动画时间间隔
 anim.duration = duration;
 //设置anim.values(多个位置点)
 NSMutableArray *arr = [NSMutableArray array];
 for (int i = 0; i < points; i++) {
 CGPoint randPoitn = [self randomPoint];
 NSValue *value = [NSValue valueWithCGPoint:randPoitn];
 [arr addObject:value];
 }
 [arr addObject:[NSValue valueWithCGPoint:point]];
 anim.values = arr;
 //指定标签赋值,方便在代理方法中回去到动画类型以及终点的值
 [anim setValue:@"randPoint" forKey:@"animationType"];
 [anim setValue:arr.lastObject forKey:@"endPoint"];
 //设置代理
   anim.delegate = self;
 //给图层添加动画
 [self.layer addAnimation:anim forKey:@"pointAnim"];
 }

 

 

3、曲线路径动画

 

【核心代码】

- (void)moveCurveWithDuratin:(CFTimeInterval)duration toPoint:(CGPoint)to{
 //创建帧动画(注意keyPath:修改的是position位置)
 CAKeyframeAnimation *anim = [CAKeyframeAnimation animationWithKeyPath:@"position"];
 //设置动画持续时间
 anim.duration = duration;
 //随机点
 CGPoint point1 = [self randomPoint];
 //随机点
 CGPoint point2 = [self randomPoint];
 //添加控制路径
 CGMutablePathRef path = CGPathCreateMutable();
 //设置路径起点
 CGPathMoveToPoint(path, NULL, self.center.x, self.center.y);
 //设置贝塞尔曲线路径控制点
 CGPathAddCurveToPoint(path, NULL, point1.x, point1.y, point2.x, point2.y, to.x, to.y);
 //将路径设置为当前动画的执行路径(如果设置了路径,values属性将失效)
 anim.path = path;
 //注意CoreGraphics框架的兑现需要手动释放(ARC不对该框架的对象做内存管理)
 CGPathRelease(path);
 //设置动画的代理
 anim.delegate = self;
 //做一个标识,在回调方法中获取动画类型,
 [anim setValue:@"moveCurve" forKey:@"animationType"];
 //做一个标识,在回调方法中获取设置的终点位置
 [anim setValue:[NSValue valueWithCGPoint:to] forKey:@"endPoint"];
 //给图层添加动画
 [self.layer addAnimation:anim forKey:@"keyframeAnimaiton"];
 }
 
 
    //通过设置values实现
 CGPoint point1 = CGPointMake(0, 0);
 NSValue *value1 = [NSValue valueWithCGPoint:point1];
 CGPoint point2 = CGPointMake(375, 50);
 NSValue *value2 = [NSValue valueWithCGPoint:point2];
 keyFrameAniamtion.values = @[value1,value2,value1];
    
     //往返路径动画(通过设置path实现)
 UIBezierPath *path1 = [UIBezierPath bezierPath];
 [path1 moveToPoint:CGPointMake(0, 0)];
 [path1 addLineToPoint:CGPointMake(375, 600)];
 [path1 addLineToPoint:CGPointMake(0, 0)];
    //矩形路径动画
 keyFrameAniamtion.path = path1.CGPath;
 keyFrameAniamtion.path = [UIBezierPath bezierPathWithRect:CGRectMake(0, 0, 375, 600)].CGPath;

 

 

【转场动画】—  CATransition

1.CATransition是CAAnimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。

 

2.UINavigationController就是通过CATransiton实现了将控制器的视图推入屏幕的视图效果。

 

3.常用动画属性

1、type: 动画过渡类型

2、subType:动画过渡方向

3、startProgress:动画起点(在整体动画中的百分比)

4、endProgress:动画终点(在整体动画中的百分比)

 

【转场动画的过渡效果】

fade 交叉淡化过渡

push 新视图把旧视图推出去 

moveIn  新视图移到旧视图上面

reveal  将旧视图移开,显示下面的新视图 

cube    立方体翻滚效果

oglFlip  上下左右翻转效果

收缩效果,如一块布被抽走

水滴效果

向上翻页效果

向下翻页效果

相机镜头打开效果

cameraIrisHollowClose  相机镜头关闭效果

 

【核心代码】

CATransition *anim = [CATransition animation];
 anim.duration = 2;
 anim.type = @"cube";
 anim.subtype = @"fromRight";
 [self.navigationController pushViewController:[[RootViewController alloc]init] animated:YES];
 [self.navigationController.view.layer addAnimation:anim forKey:@"transition"];