轉(zhuǎn)自 :http://www.360doc.com/content/17/0518/15/43221886_655008916.shtml?
作者:Sindri的小巢
從登錄動(dòng)畫說起
很長(zhǎng)一段時(shí)間以來,我都在基于CALayer層進(jìn)行動(dòng)畫實(shí)現(xiàn),卻忽略了UIKit提供給我們的動(dòng)畫接口。這些接口函數(shù)足夠的強(qiáng)大并且十分的靈活,足以滿足我們開發(fā)中大部分的動(dòng)畫需求。
在我們了解這些強(qiáng)大的接口前,我們先來看看第一個(gè)效果:在用戶打開app要進(jìn)行登錄的時(shí)候,賬戶和密碼輸入框從屏幕的左邊進(jìn)入,接著登錄按鈕出現(xiàn)。
界面動(dòng)畫
在這段動(dòng)畫之中發(fā)生的最為明顯的事情就是兩個(gè)文本框的位置變化,在動(dòng)畫開始之前,兩個(gè)文本框的位置應(yīng)該是在屏幕的左邊,而下方的按鈕現(xiàn)在是隱藏狀態(tài)(設(shè)置alpha)
動(dòng)畫開始前
因此,這個(gè)動(dòng)畫之中發(fā)生的事情,我們可以用概括為下面的代碼:
self.userName.center.x?+=?offset;????//userName進(jìn)入
self.password.center.x?+=?offset;????//password進(jìn)入
self.login.alpha?=?1;????????????????//顯示登錄按鈕
既然已經(jīng)知道了我們的動(dòng)畫發(fā)生了什么,接著就可以使用UIKit的動(dòng)畫API讓我們的動(dòng)畫活起來了
//設(shè)置文本框初始位置為屏幕左側(cè)
CGPoint?accountCenter?=?self.userName.center;
CGPoint?psdCenter?=?self.password.center;
accountCenter.x?-=?200;
pasCenter.x?-=?200;
self.userName.center?=?accountCenter;
self.password.center?=?psdCenter;
//還原中心坐標(biāo)
accountCenter.x?+=?200;
psdCenter.x?+=?200;
[UIView?animateWithDuration:?0.5?animations:?^{
self.userName.center?=?accountCenter;
self.password.center?=?passwordCenter;
self.login.alpha?=?1;
}?completion:?nil];
在UIKit中,系統(tǒng)提供了animate標(biāo)題打頭的屬于UIView的類方法讓我們可以輕松的制作動(dòng)畫效果,每一個(gè)這樣的類方法提供了名為animations的block代碼塊,這些代碼會(huì)在方法調(diào)用后立刻或者延遲一段時(shí)間以動(dòng)畫的方式執(zhí)行。此外,所有這些API的第一個(gè)參數(shù)都是用來設(shè)置動(dòng)畫時(shí)長(zhǎng)的。
在viewDidAppear:中運(yùn)行這段代碼,你會(huì)看到文本框從左側(cè)滑動(dòng),按鈕也漸變顯示出來的,但是跟我們要的結(jié)果不太一樣 —— 三個(gè)動(dòng)畫沒有錯(cuò)開,效果并不那么的好看。我們希望密碼框能在賬戶文本框滑動(dòng)后的一段時(shí)間后再出現(xiàn),按鈕同樣也需要晚一些顯示。所以,我們需要使用下面的方法來實(shí)現(xiàn)這個(gè)效果:
[UIView?animateWithDuration:?0.5?delay:?0.35?options:?UIViewAnimationOptionCurveEaseInOut?animations:?^{
self.password.center?=?passwordCenter;
}?completion:?^(BOOL?finished)?{
[UIView?animateWithDuration:?0.2?animations:?^{
self.login.alpha?=?1;
}];
}];
這個(gè)方法看起來非常的熟悉,相比上面的方法這里多了幾個(gè)參數(shù)來高度定制我們的動(dòng)畫:
duration: ?動(dòng)畫時(shí)長(zhǎng)
delay: ?決定了動(dòng)畫在延遲多久之后執(zhí)行
options:用來決定動(dòng)畫的展示方式,接下來會(huì)進(jìn)行講解
animations:轉(zhuǎn)化成動(dòng)畫表示的代碼
completion:動(dòng)畫結(jié)束后執(zhí)行的代碼塊
在上面的代碼中,密碼輸入框在延后0.35秒之后開始從左側(cè)出來,在持續(xù)0.5秒的動(dòng)畫之后,開始漸變顯示按鈕,然后動(dòng)畫完成。
可實(shí)現(xiàn)動(dòng)畫的屬性
現(xiàn)在你已經(jīng)可以制作簡(jiǎn)單的動(dòng)畫了,但要記?。翰皇撬行薷膶傩缘牟僮鞣诺絘nimations代碼塊中都是變成動(dòng)畫實(shí)現(xiàn)的 —— 不管你怎么修改一個(gè)視圖的tag,或者是delegate。因此,可實(shí)現(xiàn)動(dòng)畫的屬性必定會(huì)導(dǎo)致視圖的重新渲染。
這些可以生成動(dòng)畫的屬性大致可以分成這么三類:坐標(biāo)尺寸、視圖顯示、形態(tài)變化
坐標(biāo)尺寸類
bounds:修改這個(gè)屬性會(huì)結(jié)合center屬性重新計(jì)算frame。建議通過這個(gè)屬性修改尺寸
frame:修改這個(gè)屬性通常會(huì)導(dǎo)致視圖形變的同時(shí)也發(fā)生移動(dòng),然后會(huì)重新設(shè)置center跟bounds屬性
center: 設(shè)置后視圖會(huì)移動(dòng)到一個(gè)新位置,修改后會(huì)結(jié)合bounds重新計(jì)算frame
尺寸修改
視圖顯示類
backgroundColor: 修改這個(gè)屬性會(huì)產(chǎn)生顏色漸變過渡的效果,本質(zhì)上是系統(tǒng)不斷修改了tintColor來實(shí)現(xiàn)的
alpha:修改這個(gè)屬性會(huì)產(chǎn)生淡入淡出的效果
hidden:修改這個(gè)屬性可以制作翻頁隱藏的效果
修改透明度
形態(tài)變化類
transform:修改這個(gè)屬性可以實(shí)現(xiàn)旋轉(zhuǎn)、形變、移動(dòng)、翻轉(zhuǎn)等動(dòng)畫效果,其通過矩陣運(yùn)算的方式來實(shí)現(xiàn),因此更加強(qiáng)大
旋轉(zhuǎn)
動(dòng)畫參數(shù)
上面我們使用到的動(dòng)畫方法中有一個(gè)重要的參數(shù)options,它能讓你高度的自定義動(dòng)畫效果。下面展示這個(gè)參數(shù)類型的值集合,你可以通過結(jié)合不同的參數(shù)來實(shí)現(xiàn)自己的動(dòng)畫:
Repeating
1
2UIViewAnimationOptionRepeat//動(dòng)畫循環(huán)執(zhí)行
UIViewAnimationOptionAutoreverse//動(dòng)畫在執(zhí)行完畢后會(huì)反方向再執(zhí)行一次
我們將這兩個(gè)參數(shù)傳入到上面密碼框出現(xiàn)動(dòng)畫中,看看會(huì)有什么效果(不同的參數(shù)使用|操作符一起傳入)
[UIView?animateWithDuration:?0.5?delay:?0.35?options:?UIViewAnimationOptionAutoreverse?|?UIViewAnimationOptionRepeat?animations:?^{
self.password.center?=?passwordCenter;
}?completion:?^(BOOL?finished)?{
[UIView?animateWithDuration:?0.2?animations:?^{
self.login.alpha?=?1;
}];
}];
重復(fù)的動(dòng)畫
我們可以看到密碼框在不斷的循環(huán)進(jìn)入屏幕,反方向退出屏幕這個(gè)操作,并且登錄按鈕也始終沒有漸變出現(xiàn)。由此可以知道UIViewAnimationOptionRepeat參數(shù)不僅是讓動(dòng)畫循環(huán)播放,并且還導(dǎo)致了completion的回調(diào)永遠(yuǎn)無法執(zhí)行。
Easing
我們都知道,一個(gè)好的動(dòng)畫應(yīng)該更符合我們認(rèn)知的規(guī)則。比如,任何事物都不能突然間的開始移動(dòng)和停下,像車輛啟動(dòng)和停止都有一個(gè)加速和減速的過程。
汽車的加速減速.png
為了讓動(dòng)畫更具符合我們的認(rèn)知,系統(tǒng)同樣提供了類似的效果的參數(shù)給我們使用:
UIViewAnimationOptionCurveEaseInOut//先加速后減速,默認(rèn)
UIViewAnimationOptionCurveEaseIn//由慢到快
UIViewAnimationOptionCurveEaseOut//由快到慢
UIViewAnimationOptionCurveLinear//勻速
我在demo上創(chuàng)建了四個(gè)橙色的UIView,分別傳入這四個(gè)不同的參數(shù),然后讓這四個(gè)view在同一時(shí)間y軸上向上移動(dòng)。
[self?animatedView:?_view1];
[self?animatedView:?_view2];
[self?animatedView:?_view3];
[self?animatedView:?_view4];
//y軸上移動(dòng)視圖上升250
-?(void)animatedView:?(UIView?*)view
{
[UIView?animateWithDuration:?0.5?delay:?0?options:?UIViewAnimationOptionCurveLinear?animations:?^{
CGPoint?center?=?view.center;
center.y?-=?250;
view.center?=?center;
}?completion:?nil];
}
四種線性速度表示
在模擬器運(yùn)行狀態(tài)下,點(diǎn)擊上面的菜單欄DEBUG -> Slow Animation或者快捷鍵command + T,這會(huì)放慢我們app的動(dòng)畫運(yùn)行速度(demo在6p的模擬器上運(yùn)行)。
在減速環(huán)境下,我們看到四個(gè)view的速度變化如下:
1、逐漸加速。EaseIn
2、先加速,后減速。EaseInOut
3、速度領(lǐng)先,然后減速。EaseOut
4、勻速運(yùn)動(dòng)。Linear
運(yùn)行最開始的登錄動(dòng)畫,放慢模擬器的動(dòng)畫速度,你會(huì)看到默認(rèn)情況下使用的EaseInOut參數(shù)使得密碼框在接近結(jié)束點(diǎn)的時(shí)候出現(xiàn)了明顯的減速動(dòng)畫。
Transitioning
除了上面提到的這些效果,在視圖、圖片切換的時(shí)候,我們還能通過傳入下面的這些參數(shù)來實(shí)現(xiàn)一些特殊的動(dòng)畫效果。
UIViewAnimationOptionTransitionNone//沒有效果,默認(rèn)
UIViewAnimationOptionTransitionFlipFromLeft//從左翻轉(zhuǎn)效果
UIViewAnimationOptionTransitionFlipFromRight//從右翻轉(zhuǎn)效果
UIViewAnimationOptionTransitionCurlUp//從上往下翻頁
UIViewAnimationOptionTransitionCurlDown//從下往上翻頁
UIViewAnimationOptionTransitionCrossDissolve//舊視圖溶解過渡到下一個(gè)視圖
UIViewAnimationOptionTransitionFlipFromTop//從上翻轉(zhuǎn)效果
UIViewAnimationOptionTransitionFlipFromBottom//從上翻轉(zhuǎn)效果
那么這些參數(shù)使用的時(shí)機(jī)是什么時(shí)候呢?我們來看看這么一段代碼:
[UIView?transitionWithView:?firstPV?duration:?0.5?options:?UIViewAnimationOptionTransitionFlipFromLeft?animations:?^{
[firstPV?flipCard];
}?completion:?^(BOOL?finished)?{
isAnimating?=?NO;
}];
-?(void)flipCard
{
if(isfliped)?{
self.image?=?[UIImage?imageNamed:?@"flipPicBG.png"];
isfliped?=?NO;
}else{
self.image?=?[UIImage?imageNamed:?[NSString?stringWithFormat:?@"flipPic%d.png",?type]];
isfliped?=?YES;
}
}
這段代碼中我改變了一個(gè)UIImageView的圖片顯示,同樣用了一個(gè)動(dòng)畫的方式表現(xiàn)。這里用到了一個(gè)新的動(dòng)畫API方法,transitionWithView: duration: options: animations: completion:,這個(gè)方法跟上面的animateWithDuration系列方法相比多了一個(gè)UIView類型的參數(shù),這個(gè)參數(shù)接收的對(duì)象作為動(dòng)畫的作用者。這段代碼是我以前做的一個(gè)翻卡匹配的小游戲,點(diǎn)擊之后的動(dòng)畫效果如下:
翻卡匹配小游戲
在模擬器下使用command+T放慢了動(dòng)畫的速度之后,我截取了翻轉(zhuǎn)的四張圖片:
慢動(dòng)作翻轉(zhuǎn)
在我們切換圖片的時(shí)候,原有的圖片會(huì)基于視圖中心位置進(jìn)行x軸上的翻轉(zhuǎn),為了達(dá)到更逼真的效果,系統(tǒng)還為我們?cè)谇袚Q中加上了陰影效果(ps: 再次要說明的是,transition的動(dòng)畫你應(yīng)該只用在視圖的切換當(dāng)中 —— 你不會(huì)在移動(dòng)中產(chǎn)生任何transition效果的)
彈簧動(dòng)畫
恭喜你,你已經(jīng)可以使用UIKit的動(dòng)畫接口制作精美的動(dòng)畫了,通過組合不同的options參數(shù)你可以制作真實(shí)的動(dòng)畫。但是,我們總是能做的更多,比如一個(gè)彈簧被用力壓扁,當(dāng)松開手的時(shí)候會(huì)反復(fù)彈動(dòng)。使用上面的方式縱然可以實(shí)現(xiàn)這樣的動(dòng)畫,但代碼量復(fù)雜,也基本無復(fù)用性可言,可想而知會(huì)是糟糕的代碼。因此,我們需要其他的動(dòng)畫方式,系統(tǒng)也正好提供了這樣的一種動(dòng)畫供我們使用:
1
+?(void)animateWithDuration:(NSTimeInterval)duration?delay:(NSTimeInterval)delay?usingSpringWithDamping:(CGFloat)dampingRatio?initialSpringVelocity:(CGFloat)velocity?options:(UIViewAnimationOptions)options?animations:(void?(^)(void))animations?completion:(void?(^?__nullable)(BOOL?finished))completion
照例科普一下額外的參數(shù)信息:
dampingRatio:速度衰減比例。取值范圍0 ~ 1,值越低震動(dòng)越強(qiáng)
velocity:初始化速度,值越高則物品的速度越快
當(dāng)一個(gè)圓角按鈕高速移動(dòng)的進(jìn)入界面中,接著狠狠的震動(dòng),這絕對(duì)會(huì)狠狠地吸引住你的眼球。比如我嘗試著讓某個(gè)UICollectionView的分類按鈕從屏幕下方彈入視圖的時(shí)候;又或者我讓這個(gè)小球彈到右下角,以提示用戶該如何操作:
小球彈出效果
這效果非常的棒,在看到這些小圓球之后,你本能的會(huì)想要去點(diǎn)擊這些按鈕,而這些小球彈出的動(dòng)畫僅僅需要下面這么幾句代碼:
CGPoint?center?=?cell.center;
CGPoint?startCenter?=?center;
startCenter.y?+=?LXD_SCREEN_HEIGHT;
cell.center?=?startCenter;
[UIView?animateWithDuration:?0.5?delay:?0.35?*?indexPath.item?usingSpringWithDamping:?0.6?initialSpringVelocity:?0?options:?UIViewAnimationOptionCurveLinear?animations:?^{
cell.center?=?center;
}?completion:?nil];
除了這段彈出的代碼,在小球被點(diǎn)擊的時(shí)候,還會(huì)產(chǎn)生一個(gè)彈到右下角的動(dòng)畫,然后從左側(cè)彈出列表。這非常的酷,因?yàn)椴挥妙~外的提示,用戶會(huì)很自然的知道該怎么回到分組的界面 —— 點(diǎn)擊一下右下角的圓形按鈕。這是非常重要的,我們的動(dòng)畫應(yīng)該不僅僅只是為了讓界面更加的優(yōu)雅漂亮,還應(yīng)該能用以減少用戶學(xué)習(xí)使用app的成本,這些都是動(dòng)畫的追求。
最后
相比起PC端的粗糙,移動(dòng)端的應(yīng)用需要更加精致,精致復(fù)雜的動(dòng)畫都是源于一個(gè)個(gè)簡(jiǎn)單的動(dòng)畫組合而成的。本文作為動(dòng)畫篇的第一篇博客,目的是為了從最簡(jiǎn)單的UIView動(dòng)畫講起,慢慢的拓展其它的動(dòng)畫,也希望能起到拋磚引玉的作用。在文章的最后,如果你是iOS動(dòng)畫的初學(xué)者,請(qǐng)嘗試結(jié)合上面提到的知識(shí),為本文最開始的登錄demo中添加代碼,讓按鈕從下方漸變顯示彈出: