概述
在IOS開發中,實現動畫操作的地方有很多,典型的是在視圖控制器的segue操作時。在同一個視圖控制器類中,加載切換不同的視圖時,也需要動畫效果,還有一些視圖對象有動畫效果會更好。
插一句,在IOS開發過程中,感覺自己就像一個導演在工作,安排不同的布景,不同的畫面切換。應用有了流暢的畫面,會增色不少。
在storyboard中創建視圖和視圖控制器時,會有一些動畫設置。但在代碼角度上,我們還是需要理解一下這個動畫設置的實現過程。
動畫實現在不同的視圖控制器切換操作時如presentViewController或popViewController時,使用的是CATransition。
CATransition其實也是基於layer的實現,用於切換不同的視圖,但它能實現的效果有限。例如,不能滿足兩個視圖控制器的視圖在一個windows上展現的動畫。我是想使用panGestureController實現來自於兩個視圖控制器的視圖動畫顯示效果,這點很遺憾。
在同一視圖控制器上的不同視圖的動畫切換,可以使用UIView 的beginAnimations:nil 或animateWithDuration:animations:completion:等方法來實現。
動畫實現也就是通過修改視圖一些屬性,在設定時間能反復或逐步完成這些修改操作,達到動畫展現的效果。
這些屬性如下所示:
1.frame,bounds,center//改變View的frame屬性
2.alpha //改變透明度
3.backgroundColor//改變背景顏色
4.contentStretch//拉伸變化
5.transform//仿射變換,其中又包括Rotate,Invert,Translate,Scale(旋轉,反轉,位移,縮放)
普通的動畫都是30幀每秒,肉眼能識別的是24幀每秒,而在游戲上會要求是60幀每秒。
這些視圖就是在設置的時間內,根據時間函數如緩入、緩出等,修改它的這些屬性。修改一次,變成一個,周而復始。在我們肉眼看來,這就是一個連續的動作,就是動畫。
這裡說到UIView的屬性,就不能不說它的組成。UIView其實是由layer組成的。UIView的這些屬性如bounds,center都是來自於CALayer的對象。
在視圖的layer上,將CAAnimation的對象添加進來就能實現視圖的動畫效果。CAAnimation是一個抽象類,它的實體類有CABasicAnimation 和CAKeyframeAnimation 。
通過CABasicAnimation或CAKeyframeAnimation 對象的定義,將它加入到UIView.layer中去,實現動畫效果。注意,動畫完成後,layer的屬性定義又恢復到初始值。如果要保存動畫結果,那麼需要在添加動畫到layer時做約定設置。
例如,在一個視圖中加一個UIImage對象,聲明一個CALayer的圖層對象,將該圖層的contents設置為UIImage對象的CGImage,然後在這個圖層對象做處理。
首先,聲明一個CABasicAnimation的對象scaleAnimation的keyPath為transform.scale。
CABasicAnimation *scaleAnimation = [CABasicAnimationanimationWithKeyPath:@"transform.scale"];
然後,設置keyPath的值,動畫執行時間,動畫執行時間函數。如果需要在動畫結束後將結果保存下來,則需要在delegate的方法- (void)animationDidStop:(CAAnimation*)theAnimation finished:(BOOL)flag中去實現。
scaleAnimation.toValue =scaleFactor;
scaleAnimation.duration =3.0f;
scaleAnimation.timingFunction= [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
最後,將CABasicAnimation的對象scaleAnimation加到圖層中去,剩下就由IOS自己去實現,代碼上就到這一步了。
[self.view.layeraddSublayer:logoLayer];
詳細的代碼如下
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor =[UIColor blackColor];
self.title = [[self class]displayName];
UIImage *image = [UIImageimageNamed:@"batman.png"];
logoLayer = [CALayer layer];
logoLayer.bounds =CGRectMake(0, 0, image.size.width, image.size.height);
logoLayer.position =CGPointMake(160, 180);
logoLayer.contents =(id)image.CGImage;
// Add layer as a sublayerof the UIView's layer
[self.view.layeraddSublayer:logoLayer];
}
- (void)scaleByFactor:(CGFloat)factor {
CABasicAnimation*scaleAnimation = [CABasicAnimationanimationWithKeyPath:@"transform.scale"];
NSNumber *scaleFactor =[NSNumber numberWithFloat:factor];
scaleAnimation.toValue =scaleFactor;
scaleAnimation.duration =3.0f;
scaleAnimation.timingFunction= [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
// Set the model layer'sproperty so the animation sticks at the 'toValue' state
[logoLayer addAnimation:scaleAnimationforKey:@"transformAnimation"];
}
這裡動畫效果還只是針對一個視圖對象的,如果需要多個視圖同時操作,則需要實現動畫聯動,也就是CAAnimationGroup。將多個CABasicAnimation對象就加到一個數組中,再將這個數組設置到CAAnimationGroup的對象中,最後將CAAnimationGroup的對象加到圖層的動畫屬性中。
CAAnimationGroup*animationGroup = [CAAnimationGroup animation];
animationGroup.duration =2.0f;
animationGroup.autoreverses= YES;
animationGroup.repeatCount =HUGE_VALF;
[animationGroupsetAnimations:[NSArray arrayWithObjects:rotationAnimation, scaleAnimation,nil]];
[logoLayeraddAnimation:animationGroup forKey:@"animationGroup"];
如果需要在圖層上更精細的設置,那麼需要CALayer上做擴展,形成各種各樣的子類。
CALayer的子類有:
1) CAScrollLayer,用於簡化顯示層的一部分
2) CATextLayer,便於從字符串生成內容是文本的層
3) CATiledLayer,可用於顯示復雜的圖片
4) CAOpenGLLayer,提供OpenGLES渲染環境
CALayer能夠對 UIView 做許多設定,如:陰影、邊框、圓角和透明效果等,且這些設定都是很有用的。它的重要屬性如下。
1. shadowPath :設置 CALayer 背景(shodow)的位置
2. shadowOffset :shadow 在 X 和 Y 軸 上延伸的方向,即shadow 的大小
3. shadowOpacity: shadow 的透明效果
4. shadowRadius :shadow 的漸變距離,從外圍開始,往裡漸變 shadowRadius 距離
5. masksToBounds: 很重要的屬性,可以用此屬性來防止子元素大小溢出父元素,如若防止溢出,請設為 true
6.borderWidth 和 boarderColor : 邊框顏色和寬度,很常用
7. bounds :對於我來說比較難的一個屬性,測了半天也沒完全了解,只知道可以用來控制UIView 的大小,但是不能控制 位置
8. opacity :UIView 的透明效果
9. cornerRadius :UIView 的圓角
這些屬性和UIView的屬性很像,可以實現UIView實現不了的效果。
其實,我覺得UIKIT中聲明的那麼組件如UITextfield,uilable,uibutton,其實就是UIView的擴展,封裝好了方便使用而已。
總結
在IOS中動畫效果從layer層開始,向layer中添加CABasicAnimation對象,實際上就是layer中有一個預定義的功能,在視圖viewDidAppear後就會執行這個功能點。
可能是因為CABasicAnimation稍微復雜點,IOS又封裝出來一個類CATransition,它實現的功能有限,一些基本的動畫操作如
可能是從方便使用的角度考慮,IOS又對UIView做了可做,有了beginAnimations:nil或animateWithDuration:animations:completion:等方法,可更方便地實現一些動畫效果。
但是,如果要實現復雜的,更吸引人的動畫,還需要在CALayer上下功夫。