詳解 iOS 系統(tǒng)中的視圖動(dòng)畫
動(dòng)畫為用戶界面的狀態(tài)轉(zhuǎn)換提供了流暢的可視化效果, 在 iOS 中大量使用了動(dòng)畫效果, 包括改變視圖位置、 大小、 從可視化樹中刪除視圖, 隱藏視圖等。 你可以考慮用動(dòng)畫效果給用戶提供反饋或者用來實(shí)現(xiàn)有趣的特效。
在 iOS 系統(tǒng)中, Core Animation 提供了內(nèi)置的動(dòng)畫支持, 創(chuàng)建動(dòng)畫不需要任何繪圖的代碼, 你要做的只是激發(fā)指定的動(dòng)畫, 接下來就交給 Core Animation 來渲染, 總之, 復(fù)雜的動(dòng)畫只需要幾行代碼就可以了。
哪些屬性可以添加動(dòng)畫效果
根據(jù) iOS 視圖編程指南中說明, UIView 內(nèi)置支持為下列屬性添加動(dòng)畫效果:
- Frame 可以改變視圖相對(duì)于上一級(jí)視圖的位置和大小。 (如果視圖已經(jīng)經(jīng)過了縮放、 旋轉(zhuǎn)、平移之類的變換, 則需要修改 Center 和 Bounds 屬性)
- Bounds 改變視圖大小。
- Center 改變視圖相對(duì)于上級(jí)視圖的位置。
- Transform 相對(duì)于中心點(diǎn)進(jìn)行視圖縮放、旋轉(zhuǎn)和平移, 這個(gè)屬性只能進(jìn)行二維轉(zhuǎn)換。 (如果要進(jìn)行三維轉(zhuǎn)換, 則必須用 CoreAnimation 操作視圖的 Layer 屬性。)
- Alpha 改變視圖的透明度。
- BackgroundColor 修改視圖的背景色。
- ContentStretch 改變視圖內(nèi)容在視圖的可用空間內(nèi)的拉伸方式。
為視圖的屬性變化添加動(dòng)畫
為了給屬性的變化添加動(dòng)畫效果, 需要把修改這些屬性的代碼放到指定的動(dòng)畫代碼段 (animation block) 中。 只有在動(dòng)畫代碼段中修改支持動(dòng)畫的屬性, 才能添加動(dòng)畫效果。
使用 Begin/Commit 方法做動(dòng)畫
在 iOS 3.0 以及之前的系統(tǒng)中, 必須使用 UIView 的類方法 beginAnimations:context: 和 commitAnimations 來定義動(dòng)畫代碼段, 在 begin 和 commit 之間的代碼會(huì)在特殊的動(dòng)畫線程中運(yùn)行, 因此不會(huì)阻塞主線程, 比如說要切換兩個(gè)視圖, 代碼應(yīng)該是這樣子的:
[UIView beginAnimations:@"ToggleViews" context:nil]; [UIView setAnimationDuration:1.0]; // Make the animatable changes. firstView.alpha = 0.0; secondView.alpha = 1.0; // Commit the changes and perform the animation. [UIView commitAnimations];
在 Xamarin.iOS (MonoTouch) 平臺(tái)下, begin/end 方法對(duì)應(yīng)的綁定為:
- public static void BeginAnimations (string animation)
- public static void BeginAnimations (string animationID, IntPtr context)
- public static void CommitAnimations ()
上面的切換視圖的 C# 版本代碼為:
UIView.BeginAnimations("ToggleViews"); UIView.SetAnimationDuration(1.0) this.FirstView.Alpha = 0.0; this.SecondView.Alpha = 1.0; UIView.CommitAnidations();
在 Begin/Commit 函數(shù)之間, 可以通過下面的方法設(shè)置動(dòng)畫的參數(shù)和選項(xiàng):
- setAnimationStartDate:
- setAnimationDelay:
- setAnimationDuration:
- setAnimationCurve:
- setAnimationRepeatCount:
- setAnimationRepeatAutoreverses:
- setAnimationDelegate:
- setAnimationWillStartSelector:
- setAnimationDidStopSelector:
- setAnimationBeginsFromCurrentState:
注意: 如果不是為了支持很舊的設(shè)備, 則推薦使用下面的 lambda (block based method) 來實(shí)現(xiàn)動(dòng)畫效果, 雖然 begin/commit 還能夠使用, 按照官方的說法, 對(duì)新系統(tǒng)來說是不推薦的了。
使用 lambda (block based method) 做動(dòng)畫
在 iOS 4.0 以后, 引入了代碼塊 (code block) 的概念, 可以使用代碼塊來初始化動(dòng)畫, 這也是在 iOS 4.0 之后蘋果推薦的做法, iOS SDK 提供的 API 如下:
- animateWithDuration:animations:
- animateWithDuration:animations:completion:
- animateWithDuration:delay:options:animations:completion:
而在 Xamarin.iOS (MonoTouch) 平臺(tái)下, 這些方法被綁定為下列方法:
- public static void Animate(double duration, NSAction animation)
- public static void Animate (double duration, NSAction animation, NSAction completion)
- public static void Animate (double duration, double delay, UIViewAnimationOptions options, NSAction animation, NSAction completion)
還是切換視圖的動(dòng)畫, 如果用 objective-c 的代碼塊來實(shí)現(xiàn), 則應(yīng)該是這樣子的:
[UIView animateWithDuration:1.0 animations:^{ self.firstView.alpha = 0.0; self.secondView.alpha = 1.0; }];
如果用 C# 來實(shí)現(xiàn)的話, 應(yīng)該是這樣:
UIView.Animate(1.0, () => { this.FirstView.Alpha = 0.0f; this.SecondView.Alpha = 1.0f; });
這樣就實(shí)現(xiàn)了一個(gè)簡(jiǎn)單的漸變動(dòng)畫, 并且只能運(yùn)行一次, 通常不能滿足需求, 再來一個(gè)復(fù)雜點(diǎn)兒的:
[UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionCurveEaseIn animations:^{ self.firstView.alpha = 0.0; } completion:^(BOOL finished){ [UIView animateWithDuration:1.0 delay:1.0 options:UIViewAnimationOptionCurveEaseOut animations:^{ self.firstView.alpha = 1.0; } completion:nil]; }];
對(duì)應(yīng)的 C# 代碼如下:
UIView.Animate( 1.0, 0.0, UIViewAnimationOptions.CurveEaseIn, () => this.FirstView.Alpha = 0.0f, () => { UIView.Animate( 1.0, 1.0, UIViewAnimationOptions.CurveEaseOut, () => this.FirstView.Alpha = 1.0f, null ); } );
嵌套動(dòng)畫
iOS 支持嵌套的動(dòng)畫, 也就是說在一個(gè)動(dòng)畫代碼段中, 可以再開始另外一個(gè)動(dòng)畫代碼段, 而不必等當(dāng)前動(dòng)畫完成, 嵌套的動(dòng)畫會(huì)同時(shí)開始運(yùn)行, 默認(rèn)繼承原來動(dòng)畫的延時(shí)、 時(shí)間長(zhǎng)度、 加速曲線等, 不過這些選項(xiàng)也能被覆蓋。 例如:
[UIView animateWithDuration:1.0 delay:1.0 options:UIViewAnimationOptionCurveEaseOut animations:^{ self.firstView.alpha = 0.0f; // 這里開始一個(gè)新的動(dòng)畫 [UIView animateWithDuration:1.0 delay:0.0 options:UIViewAnimationOptionOverrideInheritedCurve | UIViewAnimationOptionCurveLinear | UIViewAnimationOptionOverrideInheritedDuration | UIViewAnimationOptionRepeat | UIViewAnimationOptionAutoreverse animations:^{ [UIView setAnimationRepeatCount:2.5]; self.secondView.alpha = 0.0f; } completion:nil]; } completion:nil ];
對(duì)應(yīng)的 C# 代碼如下:
UIView.Animate( 1.0, 1.0, UIViewAnimationOptions.CurveEaseIn, () => { this.FirstView.Alpha = 0.0; UIView.Animate( 1.0, 1.0, UIViewAnimationOptions.OverrideInheritedCurve | UIViewAnimationOptions.CurveLinear | UIViewAnimationOptions.OverrideInheritedDuration | UIViewAnimationOptions.Repeat | UIViewAnimationOptions.Autoreverse, () => { UIView.SetAnimationRepeatCount(2.f); this.SecondView.Alpha = 0.0; }, null ); }, null );
對(duì)于使用 Begin/Commit 方法的動(dòng)畫, 也可以嵌套調(diào)用 Begin/Commit 方法來實(shí)現(xiàn)嵌套的動(dòng)畫, 例如:
UIView.BeginAnimations("Animation1"); // Animation code goes here // Start another animation UIView.BeginAnimations("Nested animation"); // nested animations code goes here. UIView.CommitAnimations(); // other code UIView.CommitAnimations();
這段 C# 代碼對(duì)應(yīng)的 ObjC 代碼很簡(jiǎn)單, 就不寫出來了。
實(shí)現(xiàn)動(dòng)畫的自動(dòng)翻轉(zhuǎn)
當(dāng)創(chuàng)建自動(dòng)翻轉(zhuǎn)指定次數(shù)的動(dòng)畫時(shí), 考慮將重復(fù)次數(shù)設(shè)置為非整數(shù)值。 因?yàn)閷?duì)于自動(dòng)翻轉(zhuǎn)的動(dòng)畫來說, 每次循環(huán)都是從原始值變化到目標(biāo)值再變化回原始值, 如果希望動(dòng)畫結(jié)束之后停留在目標(biāo)值, 需要將重復(fù)次數(shù)設(shè)置加上 0.5 , 否則, 動(dòng)畫回慢慢變回原始值, 再迅速變化到目標(biāo)值, 這可能不是原來期望的動(dòng)畫效果。
創(chuàng)建視圖切換動(dòng)畫
視圖切換動(dòng)畫可以減少修改可視化樹時(shí)引起的界面上的突變, iOS 系統(tǒng)中大量使用了視圖切換動(dòng)畫, 視圖切換動(dòng)畫主要有下面兩種場(chǎng)景:
- 修改子視圖
- 替換子視圖
注意: 不要把視圖切換和視圖控制器的切換混淆(顯示一個(gè)模式對(duì)話框、將視圖控制器推入導(dǎo)航堆棧等), 視圖切換改變的僅僅是視圖的可視化樹, 視圖控制器是不變的, 更多信息可以參考iOS視圖控制器編程指南。
修改子視圖
可以修改子視圖的可見性用來表示當(dāng)前視圖的不同的狀態(tài), 看下面的兩個(gè)視圖切換的例子,在 iOS 4.0 之前, 需要將視圖切換動(dòng)畫添加到 Begin/Commit 動(dòng)畫之間, 代碼如下:
在 iOS 4.0 之后, 可以使用 transitionWithView:duration:options:animations:completion:
[UIView beginAnimations:@"toggleView" context:nil]; [UIView setAnimationTransition:UIViewAnimationTransitionCurlUp forView:self.view cache:YES]; [UIView setAnimationDuration:1.0]; // animation goes here self.currentView.hidden = YES; self.swapView.hidden = NO; [UIView commitAnimations];
這里只有動(dòng)畫部分的代碼, 動(dòng)畫完成之后請(qǐng)參考 setAnimationDelegate: 方法設(shè)置并實(shí)現(xiàn) UIAnimationDelegate 。
替換子視圖
要進(jìn)行子視圖的替換, 需要用到 transitionFromView:toView:duration:options:completion: 方法, 示例代碼如下:
UIView *fromView = (self.displayPrimary ? self.view : self.secondView); UIView *toView = (self.displayPrimary ? self.secondView : self.view); UIViewAnimationOptions option = (self.displayPrimary ? UIViewAnimationOptionTransitionFlipFromRight : UIViewAnimationOptionTransitionFlipFromLeft); [UIView transitionFromView:fromView toView:toView duration:1.0 options:option completion:^(BOOL finished) { if (finished) { self.displayPrimary = !self.displayPrimary; } } ];
鏈接多個(gè)動(dòng)畫
有了上面的知識(shí), 鏈接多個(gè)動(dòng)畫就非常簡(jiǎn)單了:
- 對(duì)于 lambda 或 block-based 方法的動(dòng)畫, 使用 complete 回調(diào)函數(shù)即可;
- 對(duì)于 Begin/Commit 方法的動(dòng)畫, 需要實(shí)現(xiàn)一個(gè) UIAnimationDelegate , 然后調(diào)用 setAnimationDelegate 方法設(shè)置 Delegate 即可。
以上就是詳解 iOS 系統(tǒng)中的視圖動(dòng)畫的詳細(xì)內(nèi)容,更多關(guān)于iOS 視圖動(dòng)畫的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
iOS中l(wèi)ebel特殊字符的自動(dòng)換行問題解決
這篇文章主要給大家介紹了關(guān)于iOS中l(wèi)ebel特殊字符的實(shí)現(xiàn)不自動(dòng)換行的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)iOS具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2017-10-10iOS開發(fā)之運(yùn)動(dòng)事件和遠(yuǎn)程控制
在iOS中事件分為三類:觸摸事件:通過觸摸、手勢(shì)進(jìn)行觸發(fā)(例如手指點(diǎn)擊、縮放),運(yùn)動(dòng)事件:通過加速器進(jìn)行觸發(fā)(例如手機(jī)晃動(dòng)),遠(yuǎn)程控制事件:通過其他遠(yuǎn)程設(shè)備觸發(fā)(例如耳機(jī)控制按鈕)今天我們來詳細(xì)探討下運(yùn)動(dòng)事件和遠(yuǎn)程控制2016-04-04iOS狀態(tài)欄frame計(jì)算問題的實(shí)現(xiàn)
這篇文章主要介紹了iOS狀態(tài)欄frame計(jì)算問題的實(shí)現(xiàn),小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-06-06詳解iOS如何讓Lottie使用網(wǎng)絡(luò)資源做動(dòng)畫的實(shí)現(xiàn)
這篇文章主要為大家介紹了iOS如何讓Lottie使用網(wǎng)絡(luò)資源做動(dòng)畫實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02