一、屏幕适配(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.equalTo or make.greaterThanOrEqualTo or make.lessThanOrEqualTo + 倍数和位移修正。
注意点1: 使用 mas_makeConstraints方法的元素必须事先添加到父元素的中,例如 [self.view addSubview:view];
注意点2: mas_equalTo 和 equalTo 区别:mas_equalTo 比equalTo多了类型转换操 ,一般来说,大多数时候两个方法都是 通用的,但是对于数值元素使用mas_equalTo。对于对象或是多个属性的处理,使用 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框架
— UIKit框架只能应用在iOS而不能用于Mac,但是Quartz 2D是可以跨平台的,因此在使用 颜色时,不能直接使用UIColor,而是需要将UIColor转换成CGColor
— 修改图层相当于修改UIView属性,即修改了界面属性
— 形变属性既可以用形变函数指定,也可以用keyPath指定(keyPath不做验证)
【x、y、z坐标系】
【图层和视图之间的关系】
1.创建视图对象时,视图会自己创建一个层,视图在绘图(如drawRect:)时,会将内容画在自己的层上。当视图在层上完成绘图后,系统会将图层拷贝至屏幕。每个视图都有一个层,而每个图层又可以有多个子图层
提示:
1> Layer的设计目的不是为了取代视图,因此不能基于CALayer常见一个独立的可视化组件
2> Layer的设计目的是提供视图的基本可视内容,从而提高动画的执行效率
3> 除提供可视内容外,Layer不负责视图的事件响应、内容绘制等工作,同时Layer不能参与到 响应者链中。
【CALayer层次结构图】
【CALayer的使用】
1.通过UIView的layer属性可以拿到对应的根层,这个层不允许重新创建,但可以往层里面添加子 层(使用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];
}
}
三、核心动画
【核心动画】
1.Core Animation是一组非常强大的动画处理API,使用它能做出非常绚丽的动画效果,而且往 往事半功倍
2.这些动画API都被封装在QuartzCore.framework中,如果要使用,需要导入头文件 <QuartzCore/QuartzCore.h>
3.开发基本步奏
1、创建一个动画(CAAnimation)对象,设置一些动画相关属性
2、CALayer很多属性都可以通过CAAnimation实现动画效果,包括:opacity、position、transform、bounds、centens等(可以在API文档中搜索CALayer Animatable Properties)
3、添加动画对象到层(CALayer)中,开始执行动画
4、通过调用CALayer的addAnimation:forKey增加动画到层(CALayer)中,这样就可以触发动画了。通过removeAnimationForKey可以停止层中的动画
5、Core Animation的动画执行过程都是在后台操作的,不会阻塞主线程
【CAAnimation的继承结构】【CAAnimation—>遵守CAMediaTiming协议(属性来源)】
【CAAnimationGroup】 【CAPropertyAnimation 】(两个子类basic,keyframe,抽象类) 【CATransition】
【CABasicAnimation】【CAKeyframeAnimation】
【CAAnimation简介】
1.是所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该 使用它的子类
2.常用属性
CFTimeInterval duration
动画的持续时间
float repeatCount:
动画重复次数,无限循环可以设置HUGE_VALF或者MAXFLOAT
NSString * fillMode:决定当前对象在非active时间段的行为。比如动画 开始之前或者动画结束之后
BOOL removedOnCompletion:默认为YES,代表动画执行完毕后就从 图层上移除,图形会恢复到动画执行前的状态。如果想让图层保 持显示动画执行后的状态,那就设置为NO,不过还要设置 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.属性说明:
fromValue: keyPath对应属性的初始值
toValue: keyPath对应属性的结束值
3.动画过程的说明:
1、随着动画的进行,在长度为duration的持续时间内,keyPath对应的属性的值从fromValue渐渐地变为toValue;
2、keyPath对应的属性是CALayer的可动画属性
3、如果fillMode=kCAFillModeForwards同时removedOnCompletion = NO,那么在动画执行完毕后,图层会保持动画执行后的状态。但在实质上,图层的属性还是动画执行前的 初始值,并没有真正被改变。
【基本动画演练】
演练内容 — 基本动画的实现
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 上下左右翻转效果
suckEffect 收缩效果,如一块布被抽走
rippleEffect 水滴效果
pageCurl 向上翻页效果
pageUnCurl 向下翻页效果
cameraIrisHollowOpen 相机镜头打开效果
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"];