您好,欢迎访问一九零五行业门户网

iOS Animation详解_html/css_WEB-ITnose

ios animation详解
本篇只要讲解ios中动画的使用.
animtion主要分为两类:uiview动画和coreanimation动画。
uiview动画有uiview属性动画,uiviewblock动画,uiviewtransition动画。
而coreanimation动画主要通过caanimation和calayer,常用的有cabasicanimation,cakeyframeanimation,catransition,caanimationgroup.
uiview官方文档 uiview 继承自:uiresponder:nsobject
遵循:uitraitenvironment, uidynamicitem, nsobject, uicoordinatespace, uiappearancecontainer, uiappearance, nscoding
框架:ios 2.0及以后版本的uikit
因为view对象是应用与用户交互的主要途径,他们有一系列的职责。以下列出一些:
绘画和动画:
view在他们的矩形区域使用uikit,core graphics和opengl es之类的技术绘画 一些视图属性可以动画到新的值 布局和子view管理
一个view可以包含0个或多个子view 每个view都定义了相对父view大小改变的默认行为 如有需要,一个view可以定义子view的大小和位置 事件处理
view是一个响应者,可以处理uiresponder类定义的触摸和其他事件 view可以使用addgesturerecognizer方法安装手势识别器来处理常用手势 view可以内嵌到其他view,创建复杂的可视层级。这会在嵌入的view(子view)和被嵌入的view(父view)间创建父子关系。正常情况下,子view的可视区域不会被父view的边界剪辑,但在ios里你可以使用clipstobounds属性来修改这个行为。一个父view可能有多个子view,但一个子view只有一个父view,它负责确定子view的位置。
view的几何结构是通过它的框架(frame),边界(bounds)和中心(center)属性来定义的。frame定义了view相对父view坐标系的原点和大小,一般在view布局和调整尺寸或位置时使用。center属性可以在不改变view的大小来调整view的位置。bounds定义了view的内部尺寸,几乎只在自定义绘画代码时使用。frame的size部分和bounds矩形部分耦合在一起,所以可以使用两者中的一个或两个同时来改变view的大小。
创建一个view 用代码来创建view:
swift:
let viewrect = cgrect(x: 10, y: 10, width: 100, height: 100)let myview = uiview(frame: viewrect)
objective-c
cgrect viewrect = cgrectmake(10, 10, 100, 100);uiview* myview = [[uiview alloc] initwithframe:viewrect];
这段代码创建了view,并把它放在父view坐标系的(10,10)点(一旦它被加到父view)。添加一个子view到另一个view上,用addsubview:方法。在ios里,同级的view可以相互覆盖,而不会有任何问题,允许复杂的view布置。addsubview放置指定的view到它的同级view的顶部。你可以使用insertsubview:abovesubview: 和 insertsubview:belowsubview: 方法指定子view的相对z坐标。你也可以使用exchangesubviewatindex:withsubviewatindex: 方法交换已经添加的子view的位置。
view绘画周期 view绘画发生在需要时。当一个view第一次展示时,或者在布局变化时,它的整体或部分变得可见时,系统请求view绘出它的内容。对那些使用uikit或core graphics包含自定义内容的view来说,系统会调用它的drawrect: 方法。你对该方法的实现,负责将view的内容画进当前的图形上下文(graphics context),系统自动优先调用该方法。这里创建了view内容的静态可视展现,接着会被展示在屏幕上。
当view的真实内容发生改变时,你有责任通知系统你的view需要重绘。通过调用view的setneedsdisplay或setneedsdisplayinrect:方法来通知。这些方法让系统知道它应该在下次绘画周期更新view.因为它一直等待直到下次绘画周期来更新view,你可以在多个view上调用这些方法,同时更新它们.
动画 改变多个view属性可以被动画展现,在一个短周期时间内,改变属性可以创建动画。uiview类做了很多执行动画的工作,但你仍然必须判断你需要哪些属性改变被动画。下面是两种不同的初始化动画方法:
在ios4.0及以后的版本中,使用基于块的动画方法(推荐) 使用开始/提交(begin/commit)动画方法。 基于块的动画方法(像animatewithduration:animations:)极大地简化了动画创建。只要调用一个方法,指定动画的参数,并且执行动画。然后,基于块的动画仅在ios4及以后版本中可用。如果你的设备运行老版本的ios,必须使用beginanimations:context: 和 commitanimations类方法标记动画开始和结束。
下面是动画属性:
@property frame @property bounds @property center @property transform @property alpha @property backgroundcolor @property contentstretch 线程注意事项
操作用户界面必须发生在主线程。因此,你必须在应用主线程调用uiview类的方法。只有在创建view对象自身时可以不用严格遵守,但其他操作必须在主线程中。
子类化说明 对同样需要用户交互的可见内容来说,uiview类是一个关键的子类化点。尽管有很多好理由继承uiview,但我们只推荐在基本的uiview和系统自带的其他组件不能满足需要时继承uiview.继承uiview会在你实现的代码里消耗更多性能.(apple写的代码比你的更好,有现成的就用现成的)。
覆盖方法 当子类化uiview时,只有少数的方法你必须覆盖,大多数方法你可以按需覆盖。因为uiview是一个高度可配的类,不用覆盖父类方法,同样有很多实现复杂的行为的途径,这些在 选择子类化 一节中介绍。你可以在你的uiview子类中考虑覆盖下面列表中的方法:
初始化
initwithframe 推荐覆盖。你同样可以实现自定义的初始化方法添加或代替此方法 initwithcoder: 如果你从一个interface builder的nib文件加载view,并且需要自定义初始化,覆盖该方法。 layerclass 仅当你的view需要用不同的core animation层后备保存时才要覆盖。例如,当你的view需要用平铺方式显示一块很大的可滚动区域时,你可能想要覆盖该方法返回catiledlayer类.(不是很明白,原文: implement this method only if you want your view to use a different core animation layer for its backing store. for example, if your view uses tiling to display a large scrollable area, you might want to override this method and return the catiledlayer class.) 绘画和打印
drawrect: 如果你的view画自定义的内容,就要实现该方法,否则避免覆盖该方法。 drawrect:forviewprintformatter: 仅当你需要在打印时,打印不同内容(与显示不同)才需要实现该方法。 约束
requiresconstraintbasedlayout ? 如果你的view类需要约束才能正常工作,实现该方法 updateconstraints 如果你的view需要在子view间创建约束,需要实现该方法 alignmentrectforframe:, frameforalignmentrect: ? 实现这些方法覆盖你的view如何与其他view对齐 布局
sizethatfits: ? 当你想在执行resize操作时有一个不同于默认的size,实现该方法。比如,你可以用这个方法阻止view收缩到子view不能正确显示的点 layoutsubviews ? 如果你需要更精确控制子view,而不是使用限制或autoresizing行为,就需要实现该方法。 didaddsubview: , willremovesubview: 跟踪子view添加或删除事件 willmovetosuperview:, didmovetosuperview 跟踪当前view在view层次里的运动 willmovetowindow:,didmovetowindow 跟踪view(即将或已经)移动到另一个window
事件处理: touchesbegan:withevent:, touchesmoved:withevent:, touchesended:withevent:, touchescancelled:withevent: 直接处理触摸事件(如果是手势,使用gesture recognizers) gesturerecognizershouldbegin: 如果需要直接处理触摸事件,那么需要覆盖该方法,阻止手势识别器触发额外动作。 替代子类化 很多view行为可以配置而不用子类化。在你开始覆盖这些方法时,考虑是否可以修改下面的属性或行为来提供你需要的功能。
addconstraint: ? 为view和它的子view定义自动布局行为. autoresizingmask ? 当父view的frame改变时,提供自动布局行为。这些行为可以和约束(constraint)合并 contentmode -为view内容提供布局行为,与view的frame相反。这个属性同样影响内容应用view的缩放,是缓存还是重绘。 contentstretch-定义view的部分可伸缩。这个行为通常用于实现按钮和其他复杂布局、可变尺寸、重绘代价高的view。 hidden 或 alpha 改变view的不透明度或隐藏view backgroundcolor ? 设置view的背景颜色 subviews 不在drawrect方法里绘制你的内容,使用嵌入图片或文本子view等方式 gesture recognizers ? 使用手势识别器替代自己手工处理touch事件 animations ? 使用内建动画支持代替自己写动画。core animation提供的动画支持很快很好用 基于图片的背景 ? 对那些显示相对静态内容的view来说,考虑使用uiimageview对象加上手势识别替代子类化和自己绘制图片。同样,你也可以使用一般的uiview对象,分配你的图片作为view的calayer对象内容。 动画是不需要子类化和实现复杂代码而让视觉改变的另一种方式。很多uiview的属性是可以动画的,意味着改变这些属性可以触发系统生成动画。启动动画只需要很少的一行代码指示那些改变需要被动画。更多view动画的信息,参考animations.
uiview动画 uiview属性动画 cgrect viewrect = cgrectmake(10,10,200,200);self.myview= [[uiview alloc] initwithframe:viewrect];self.myview.backgroundcolor = [uicolor whitecolor];[self.view addsubview:self.myview];//1 准备动画//参数1: 动画的作用, 任意字符串,用来区分多个动画, 参数二: 传递参数用 nil:oc中使用[uiview beginanimations:@changesizeandcolor context:nil];//在准备动画的时候可以设置动画的属性[uiview setanimationduration:0.7];[uiview setanimationdelegate:self];[uiview setanimationwillstartselector:@selector(startanimation)];[uiview setanimationcurve:uiviewanimationcurveeaseinout];//动画的曲线[uiview setanimationrepeatcount:2];[uiview setanimationrepeatautoreverses:yes];//动画往返执行, 必须设置动画的重复次数//2 修改view的属性, 可以同时修改多个属性 注意:不是所有的属性都可以修改的(只有frame, center, bounds, backgroundcolor, alpha, transform 可以修改)self.myview.frame = cgrectmake(110, 100, 100, 100);self.myview.backgroundcolor = [uicolor colorwithred:arc4random() % 256 / 255.0 green:arc4random() % 256 / 255.0 blue:arc4random() % 256 / 255.0 alpha:0.5];//3 提交并执行动画[uiview commitanimations];
block动画 block动画的实质是对uiview动画的封装
第一种
[uiview animatewithduration:2 animations:^{ self.myview.backgroundcolor = [uicolor orangecolor]; }];
第二种
[uiview animatewithduration:2 animations:^{ self.myview.backgroundcolor = [uicolor orangecolor]; } completion:^(bool finished) { //finished判断动画是否完成 if (finished) { nslog(@finished); } }];
第三种
[uiview animatewithduration:2 delay:1 options:uiviewanimationoptioncurveeaseinout animations:^{ // 设置要修改的view属性 self.myview.backgroundcolor = [uicolor orangecolor]; } completion:^(bool finished) { //finished判断动画是否完成 if (finished) { nslog(@finished); } }];
下面是animationoptioncurve参数:
uiviewanimationoptioncurveeaseinout = 0 << 16, // default uiviewanimationoptioncurveeasein = 1 << 16, uiviewanimationoptioncurveeaseout = 2 << 16, uiviewanimationoptioncurvelinear = 3 << 16,
uiviewtransition动画 [uiview transitionwithview:self.myview duration:2 options:uiviewanimationoptiontransitionflipfromleft animations:^{ self.myview.backgroundcolor = [uicolor orangecolor]; } completion:^(bool finished) { //finished判断动画是否完成 if (finished) { nslog(@finished); } }];
下面是animationoptiontransition参数:
uiviewanimationoptiontransitionnone = 0 << 20, // default uiviewanimationoptiontransitionflipfromleft = 1 << 20, uiviewanimationoptiontransitionflipfromright = 2 << 20, uiviewanimationoptiontransitioncurlup = 3 << 20, uiviewanimationoptiontransitioncurldown = 4 << 20, uiviewanimationoptiontransitioncrossdissolve = 5 << 20, uiviewanimationoptiontransitionflipfromtop = 6 << 20, uiviewanimationoptiontransitionflipfrombottom = 7 < 组中所有动画的最长时长, 动画的时长以组中最长的时长为准 //当group动画的时长 < 组中所有动画的最长时长, 动画的时长以group的时长为准 //最合适: group的时长 = 组中所有动画的最长时长 caanimationgroup *group = [caanimationgroup animation]; [group setduration:10]; //设置组动画 group.animations = @[basic, keyframe]; //添加动画 [self.myview.layer addanimation:group forkey:nil];
coreanimation相关知识 caanimation 所有动画对象的父类,负责控制动画的持续时间和速度,是个抽象类,不能直接使用,应该使用它具体的子类.
属性解析:
duration:动画的持续时间 .repeatcount:动画的重复次数 .repeatduration:动画的重复时间 .removedoncompletion:默认为yes,代表动画执行完毕后就从图层上移除,图形会恢复到动画执行前的状态。如果想让图层保持显示动画执行后的状态,那就设置为no,不过还要设置fillmode为kcafillmodeforwards .fillmode:决定当前对象在非active时间段的行为.比如动画开始之前,动画结束之后 .begintime:可以用来设置动画延迟执行时间,若想延迟2s,就设置为cacurrentmediatime()+2, cacurrentmediatime()为图层的当前时间 .timingfunction:速度控制函数,控制动画运行的节奏 .delegate:动画代理
速度控制函数(camediatimingfunction)
1. kcamediatimingfunctionlinear(线性):匀速,给你一个相对静态的感觉2. kcamediatimingfunctioneasein(渐进):动画缓慢进入,然后加速离开3. kcamediatimingfunctioneaseout(渐出):动画全速进入,然后减速的到达目的地4. kcamediatimingfunctioneaseineaseout(渐进渐出):动画缓慢的进入,中间加速,然后减速的到达目的地。 这个是默认的动画行为。
caanimation在分类中定义了代理方法
@interface nsobject - (void)animationdidstart:(caanimation *)anim;- (void)animationdidstop:(caanimation *)anim finished:(bool)flag;@end
fillmode属性值(要想fillmode有效,最好设置removedoncompletion=no)
kcafillmoderemoved 这个是默认值,也就是说当动画开始前和动画结束后,动画对layer都没有影响,动画结束后,layer会恢复到之前的状态?.
kcafillmodeforwards 当动画结束后,layer会一直保持着动画最后的状态.
?kcafillmodebackwards 在动画开始前,你只要将动画加入了一个layer,layer便立即进入动画的初始状态并等待动画开始. 你可以这样设定测试代码,将一个动画加入一个layer的时候延迟5秒执行.然后就会发现在动画没有开始的时候,只要动画被加入了layer,layer便处于动画初始状态 ?
kcafillmodeboth 这个其实就是上面两个的合成.动画加入后开始之前,layer便处于动画初始状态,动画结束后layer保持动画最后的状
capropertyanimation caanimation的子类,也是个抽象类,要想创建动画对象,应该使用它的两个子类:cabasicanimation和cakeyframeanimation.
属性解析:
keypath:
通过指定calayer的一个属性名称为keypath(nsstring类型),并且对calayer的这个属性的值进行修改,达到相应的动画效果。比如,指定@”position”为keypath,就修改calayer的position属性的值,以达到平移的动画效果
cabasicanimation
capropertyanimation的子类 .
属性解析:
fromvalue:keypath相应属性的初始值 .tovalue:keypath相应属性的结束值 .随着动画的进行,在长度为duration的持续时间内,keypath相应属性的值从fromvalue渐渐地变为tovalue .
如果fillmode=kcafillmodeforwards和removedoncomletion=no,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值还是动画执行前的初始值,并没有真正被改变。比如,calayer的position初始值为(0,0),cabasicanimation的fromvalue为(10,10),tovalue为(100,100),虽然动画执行完毕后图层保持在(100,100)这个位置,实质上图层的position还是为(0,0)
//平移动画cabasicanimation *anim = [cabasicanimation animationwithkeypath:@position];// 动画持续1秒anim.duration =1; //因为cgpoint是结构体,所以用nsvalue包装成一个oc对象anim.fromvalue = [nsvalue valuewithcgpoint:cgpointmake(50, 50)];anim.tovalue = [nsvalue valuewithcgpoint:cgpointmake(100, 100)];//通过myanim可以取回相应的动画对象,比如用来中途取消动画[layer addanimation:anim forkey:@myanim];//缩放动画cabasicanimation *anim = [cabasicanimation animationwithkeypath:@transform];//没有设置fromvalue说明当前状态作为初始值//宽度(width)变为原来的2倍,高度(height)变为原来的1.5倍anim.tovalue = [nsvaluevaluewithcatransform3d:catransform3dmakescale(2, 1.5, 1)];anim.duration = 1;[layer addanimation:anim forkey:nil];//旋转动画cabasicanimation *anim = [cabasicanimation animationwithkeypath:@transform];//这里是以向量(1, 1, 0)为轴,旋转π/2弧度(90°)//如果只是在手机平面上旋转,就设置向量为(0, 0, 1),即z轴anim.tovalue = [nsvaluevaluewithcatransform3d:catransform3dmakerotation(m_pi_2, 1, 1, 0)];anim.duration = 1;[layer addanimation:anim forkey:nil];
cakeyframeanimation capropertyanimation的子类,跟cabasicanimation的区别是:
cabasicanimation只能从一个数值(fromvalue)变到另一个数值(tovalue),而cakeyframeanimation会使用一个nsarray保存这些数值 .
属性解析:
values:就是上述的nsarray对象。里面的元素称为”关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每一个关键帧 .path:可以设置一个cgpathref\cgmutablepathref,让层跟着路径移动。path只对calayer的anchorpoint和position起作用。如果你设置了path,那么values将被忽略 .keytimes:可以为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keytimes中的每一个时间值都对应values中的每一帧.当keytimes没有设置的时候,各个关键帧的时间是平分的 .cabasicanimation可看做是最多只有2个关键帧的cakeyframeanimation在关键帧动画中还有一个非常重要的参数,那便是calculationmode,计算模式.其主要针对的是每一帧的内容为一个座标点的情况,也就是对anchorpoint 和 position 进行的动画.当在平面座标系中有多个离散的点的时候,可以是离散的,也可以直线相连后进行插值计算,也可以使用圆滑的曲线将他们相连后进行插值计算. calculationmode目前提供如下几种模式:kcaanimationlinear calculationmode的默认值,表示当关键帧为座标点的时候,关键帧之间直接直线相连进行插值计算;
?kcaanimationdiscrete 离散的,就是不进行插值计算,所有关键帧直接逐个进行显示;
?kcaanimationpaced 使得动画均匀进行,而不是按keytimes设置的或者按关键帧平分时间,此时keytimes和timingfunctions无效;
?kcaanimationcubic 对关键帧为座标点的关键帧进行圆滑曲线相连后插值计算,这里的主要目的是使得运行的轨迹变得圆滑;
kcaanimationcubicpaced 看这个名字就知道和kcaanimationcubic有一定联系,其实就是在kcaanimationcubic的基础上使得动画运行变得均匀,就是系统时间内运动的距离相同,此时keytimes以及timingfunctions也是无效的.
caanimationgroup
caanimation的子类,可以保存一组动画对象,将caanimationgroup对象加入层后,组中所有动画对象可以同时并发运行.
属性解析:
animations:用来保存一组动画对象的nsarray.默认情况下,一组动画对象是同时运行的,也可以通过设置动画对象的begintime属性来更改动画的开始时间.
catransition caanimation的子类,用于做转场动画,能够为层提供移出屏幕和移入屏幕的动画效果。ios比mac os x的转场动画效果少一点.
uinavigationcontroller就是通过catransition实现了将控制器的视图推入屏幕的动画效果.
属性解析:
type:动画过渡类型subtype:动画过渡方向startprogress:动画起点(在整体动画的百分比)endprogress:动画终点(在整体动画的百分比)
/* 过渡效果 fade //交叉淡化过渡(不支持过渡方向) kcatransitionfade push //新视图把旧视图推出去 kcatransitionpush movein //新视图移到旧视图上面 kcatransitionmovein reveal //将旧视图移开,显示下面的新视图 kcatransitionreveal cube //立方体翻滚效果 oglflip //上下左右翻转效果 suckeffect //收缩效果,如一块布被抽走(不支持过渡方向) rippleeffect //滴水效果(不支持过渡方向) pagecurl //向上翻页效果 pageuncurl //向下翻页效果 camerairishollowopen //相机镜头打开效果(不支持过渡方向) camerairishollowclose //相机镜头关上效果(不支持过渡方向) */ /* 过渡方向 kcatransitionfromright kcatransitionfromleft kcatransitionfrombottom kcatransitionfromtop */// catransition的使用 catransition *anim = [catransition animation];anim.type = @cube; // 动画过渡类型anim.subtype = kcatransitionfromtop; // 动画过渡方向anim.duration = 1; // 动画持续1s// 代理,动画执行完毕后会调用delegate的animationdidstop:finished:anim.delegate = self;
后记 另外还有 uiimageview的帧动画 和 uiactivityindicatorview,这里就暂不介绍了。
参考文档
http://www.pocketdigi.com/20150105/1413.html
版权声明:本文为博主原创文章,未经博主允许不得转载。
其它类似信息

推荐信息