毋庸置疑的:在iOS開發中,製作動畫效果是最讓開發者享受的環節之一。一個設計嚴謹、精細的動畫效果能給使用者耳目一新的效果,吸引他們的眼光 —— 這對於app而言是非常重要的。
本文作為動畫文集的第一篇,最開始是想做個qq下拉重新整理的水滴動畫的製作講解,但這幾天研讀《iOS Animations by Tutorials》一書,對iOS動畫開發有了更為深刻的瞭解,於是決定動畫篇將從UIView動畫開始講起,以後還會有Layer、Transitioning等在內的動畫,希望本文能拋磚引玉,帶給大家不一樣的理解,下面送上一張書中demo的效果圖。購買書籍
先放上本文demo:點這
ps:本文屬於新手向的動畫入門文章
從登入動畫說起
很長一段時間以來,我都在基於CALayer層進行動畫實現,卻忽略了UIKit提供給我們的動畫介面。這些介面函式足夠的強大並且十分的靈活,足以滿足我們開發中大部分的動畫需求。
在我們瞭解這些強大的介面前,我們先來看看第一個效果:在使用者開啟app要進行登入的時候,賬戶和密碼輸入框從螢幕的左邊進入,接著登入按鈕出現。
在這段動畫之中發生的最為明顯的事情就是兩個文字框的位置變化,在動畫開始之前,兩個文字框的位置應該是在螢幕的左邊,而下方的按鈕現在是隱藏狀態(設定alpha)
因此,這個動畫之中發生的事情,我們可以用概括為下面的程式碼:
1 2 3 |
self.userName.center.x += offset; //userName進入 self.password.center.x += offset; //password進入 self.login.alpha = 1; //顯示登入按鈕 |
既然已經知道了我們的動畫發生了什麼,接著就可以使用UIKit
的動畫API讓我們的動畫活起來了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//設定文字框初始位置為螢幕左側 CGPoint accountCenter = self.userName.center; CGPoint psdCenter = self.password.center; accountCenter.x -= 200; pasCenter.x -= 200; self.userName.center = accountCenter; self.password.center = psdCenter; //還原中心座標 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中,系統提供了animate
標題打頭的屬於UIView
的類方法讓我們可以輕鬆的製作動畫效果,每一個這樣的類方法提供了名為animations
的block
程式碼塊,這些程式碼會在方法呼叫後立刻或者延遲一段時間以動畫的方式執行。此外,所有這些API的第一個引數都是用來設定動畫時長的。
在viewDidAppear:
中執行這段程式碼,你會看到文字框從左側滑動,按鈕也漸變顯示出來的,但是跟我們要的結果不太一樣 —— 三個動畫沒有錯開,效果並不那麼的好看。我們希望密碼框能在賬戶文字框滑動後的一段時間後再出現,按鈕同樣也需要晚一些顯示。所以,我們需要使用下面的方法來實現這個效果:
1 2 3 4 5 6 7 |
[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; }]; }]; |
這個方法看起來非常的熟悉,相比上面的方法這裡多了幾個引數來高度定製我們的動畫:
- duration: 動畫時長
- delay: 決定了動畫在延遲多久之後執行
- options:用來決定動畫的展示方式,接下來會進行講解
- animations:轉化成動畫表示的程式碼
- completion:動畫結束後執行的程式碼塊
在上面的程式碼中,密碼輸入框在延後0.35秒之後開始從左側出來,在持續0.5秒的動畫之後,開始漸變顯示按鈕,然後動畫完成。
可實現動畫的屬性
現在你已經可以製作簡單的動畫了,但要記住:不是所有修改屬性的操作放到animations
程式碼塊中都是變成動畫實現的 —— 不管你怎麼修改一個檢視的tag
,或者是delegate
。因此,可實現動畫的屬性必定會導致檢視的重新渲染。
這些可以生成動畫的屬性大致可以分成這麼三類:座標尺寸
、檢視顯示
、形態變化
座標尺寸類
- bounds:修改這個屬性會結合
center
屬性重新計算frame
。建議通過這個屬性修改尺寸 - frame:修改這個屬性通常會導致檢視形變的同時也發生移動,然後會重新設定
center
跟bounds
屬性 - center: 設定後檢視會移動到一個新位置,修改後會結合
bounds
重新計算frame
尺寸修改
檢視顯示類
- backgroundColor: 修改這個屬性會產生顏色漸變過渡的效果,本質上是系統不斷修改了tintColor來實現的
- alpha:修改這個屬性會產生淡入淡出的效果
- hidden:修改這個屬性可以製作翻頁隱藏的效果
修改透明度
形態變化類
- transform:修改這個屬性可以實現旋轉、形變、移動、翻轉等動畫效果,其通過矩陣運算的方式來實現,因此更加強大
旋轉
動畫引數
上面我們使用到的動畫方法中有一個重要的引數options
,它能讓你高度的自定義動畫效果。下面展示這個引數型別的值集合,你可以通過結合不同的引數來實現自己的動畫:
- Repeating
12UIViewAnimationOptionRepeat //動畫迴圈執行UIViewAnimationOptionAutoreverse //動畫在執行完畢後會反方向再執行一次
我們將這兩個引數傳入到上面密碼框出現動畫中,看看會有什麼效果(不同的引數使用|
操作符一起傳入)
1234567[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;}];}];重複的動畫我們可以看到密碼框在不斷的迴圈進入螢幕,反方向退出螢幕這個操作,並且登入按鈕也始終沒有漸變出現。由此可以知道
UIViewAnimationOptionRepeat
引數不僅是讓動畫迴圈播放,並且還導致了completion
的回撥永遠無法執行。 - Easing
我們都知道,一個好的動畫應該更符合我們認知的規則。比如,任何事物都不能突然間的開始移動和停下,像車輛啟動和停止都有一個加速和減速的過程。汽車的加速減速.png為了讓動畫更具符合我們的認知,系統同樣提供了類似的效果的引數給我們使用:
1234UIViewAnimationOptionCurveEaseInOut //先加速後減速,預設UIViewAnimationOptionCurveEaseIn //由慢到快UIViewAnimationOptionCurveEaseOut //由快到慢UIViewAnimationOptionCurveLinear //勻速我在demo上建立了四個橙色的UIView,分別傳入這四個不同的引數,然後讓這四個view在同一時間y軸上向上移動。
1234567891011121314[self animatedView: _view1];[self animatedView: _view2];[self animatedView: _view3];[self animatedView: _view4];//y軸上移動檢視上升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];}四種線性速度表示在模擬器執行狀態下,點選上面的選單欄
DEBUG -> Slow Animation
或者快捷鍵command + T
,這會放慢我們app的動畫執行速度(demo在6p的模擬器上執行)。
在減速環境下,我們看到四個view的速度變化如下:
1、逐漸加速。EaseIn
2、先加速,後減速。EaseInOut
3、速度領先,然後減速。EaseOut
4、勻速運動。Linear
執行最開始的登入動畫,放慢模擬器的動畫速度,你會看到預設情況下使用的EaseInOut
引數使得密碼框在接近結束點的時候出現了明顯的減速動畫。 - Transitioning
除了上面提到的這些效果,在檢視、圖片切換的時候,我們還能通過傳入下面的這些引數來實現一些特殊的動畫效果。12345678UIViewAnimationOptionTransitionNone //沒有效果,預設UIViewAnimationOptionTransitionFlipFromLeft //從左翻轉效果UIViewAnimationOptionTransitionFlipFromRight //從右翻轉效果UIViewAnimationOptionTransitionCurlUp //從上往下翻頁UIViewAnimationOptionTransitionCurlDown //從下往上翻頁UIViewAnimationOptionTransitionCrossDissolve //舊檢視溶解過渡到下一個檢視UIViewAnimationOptionTransitionFlipFromTop //從上翻轉效果UIViewAnimationOptionTransitionFlipFromBottom //從上翻轉效果那麼這些引數使用的時機是什麼時候呢?我們來看看這麼一段程式碼:
12345678910111213141516[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;}}這段程式碼中我改變了一個
UIImageView
的圖片顯示,同樣用了一個動畫的方式表現。這裡用到了一個新的動畫API方法,transitionWithView: duration: options: animations: completion:
,這個方法跟上面的animateWithDuration
系列方法相比多了一個UIView
型別的引數,這個引數接收的物件作為動畫的作用者。這段程式碼是我以前做的一個翻卡匹配的小遊戲,點選之後的動畫效果如下:翻卡匹配小遊戲在模擬器下使用
command+T
放慢了動畫的速度之後,我擷取了翻轉的四張圖片:慢動作翻轉在我們切換圖片的時候,原有的圖片會基於檢視中心位置進行x軸上的翻轉,為了達到更逼真的效果,系統還為我們在切換中加上了陰影效果(ps: 再次要說明的是,transition的動畫你應該只用在檢視的切換當中 —— 你不會在移動中產生任何transition效果的)
彈簧動畫
恭喜你,你已經可以使用UIKit
的動畫介面製作精美的動畫了,通過組合不同的options
引數你可以製作真實的動畫。但是,我們總是能做的更多,比如一個彈簧被用力壓扁,當鬆開手的時候會反覆彈動。使用上面的方式縱然可以實現這樣的動畫,但程式碼量複雜,也基本無複用性可言,可想而知會是糟糕的程式碼。因此,我們需要其他的動畫方式,系統也正好提供了這樣的一種動畫供我們使用:
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 |
照例科普一下額外的引數資訊:
- dampingRatio:速度衰減比例。取值範圍0 ~ 1,值越低震動越強
- velocity:初始化速度,值越高則物品的速度越快
當一個圓角按鈕高速移動的進入介面中,接著狠狠的震動,這絕對會狠狠地吸引住你的眼球。比如我嘗試著讓某個UICollectionView
的分類按鈕從螢幕下方彈入檢視的時候;又或者我讓這個小球彈到右下角,以提示使用者該如何操作:
這效果非常的棒,在看到這些小圓球之後,你本能的會想要去點選這些按鈕,而這些小球彈出的動畫僅僅需要下面這麼幾句程式碼:
1 2 3 4 5 6 7 8 |
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]; |
除了這段彈出的程式碼,在小球被點選的時候,還會產生一個彈到右下角的動畫,然後從左側彈出列表。這非常的酷,因為不用額外的提示,使用者會很自然的知道該怎麼回到分組的介面 —— 點選一下右下角的圓形按鈕。這是非常重要的,我們的動畫應該不僅僅只是為了讓介面更加的優雅漂亮,還應該能用以減少使用者學習使用app的成本,這些都是動畫的追求。
最後
相比起PC端的粗糙,移動端的應用需要更加精緻,精緻複雜的動畫都是源於一個個簡單的動畫組合而成的。本文作為動畫篇的第一篇部落格,目的是為了從最簡單的UIView
動畫講起,慢慢的擴充其它的動畫,也希望能起到拋磚引玉的作用。在文章的最後,如果你是iOS動畫的初學者,請嘗試結合上面提到的知識,為本文最開始的登入demo中新增程式碼,讓按鈕從下方漸變顯示彈出:
最後的最後,吐槽一下gitcafe。本來以為託管到gitcafe後個人部落格在國內的訪問速度會提高,結果今天部落格更新了兩小時,還顯示不出來。