詳解 iOS 系統(tǒng)中的視圖動畫
動畫為用戶界面的狀態(tài)轉(zhuǎn)換提供了流暢的可視化效果, 在 iOS 中大量使用了動畫效果, 包括改變視圖位置、 大小、 從可視化樹中刪除視圖, 隱藏視圖等。 你可以考慮用動畫效果給用戶提供反饋或者用來實現(xiàn)有趣的特效。
在 iOS 系統(tǒng)中, Core Animation 提供了內(nèi)置的動畫支持, 創(chuàng)建動畫不需要任何繪圖的代碼, 你要做的只是激發(fā)指定的動畫, 接下來就交給 Core Animation 來渲染, 總之, 復雜的動畫只需要幾行代碼就可以了。
哪些屬性可以添加動畫效果
根據(jù) iOS 視圖編程指南中說明, UIView 內(nèi)置支持為下列屬性添加動畫效果:
- Frame 可以改變視圖相對于上一級視圖的位置和大小。 (如果視圖已經(jīng)經(jīng)過了縮放、 旋轉(zhuǎn)、平移之類的變換, 則需要修改 Center 和 Bounds 屬性)
- Bounds 改變視圖大小。
- Center 改變視圖相對于上級視圖的位置。
- Transform 相對于中心點進行視圖縮放、旋轉(zhuǎn)和平移, 這個屬性只能進行二維轉(zhuǎn)換。 (如果要進行三維轉(zhuǎn)換, 則必須用 CoreAnimation 操作視圖的 Layer 屬性。)
- Alpha 改變視圖的透明度。
- BackgroundColor 修改視圖的背景色。
- ContentStretch 改變視圖內(nèi)容在視圖的可用空間內(nèi)的拉伸方式。
為視圖的屬性變化添加動畫
為了給屬性的變化添加動畫效果, 需要把修改這些屬性的代碼放到指定的動畫代碼段 (animation block) 中。 只有在動畫代碼段中修改支持動畫的屬性, 才能添加動畫效果。
使用 Begin/Commit 方法做動畫
在 iOS 3.0 以及之前的系統(tǒng)中, 必須使用 UIView 的類方法 beginAnimations:context: 和 commitAnimations 來定義動畫代碼段, 在 begin 和 commit 之間的代碼會在特殊的動畫線程中運行, 因此不會阻塞主線程, 比如說要切換兩個視圖, 代碼應該是這樣子的:
[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) 平臺下, begin/end 方法對應的綁定為:
- 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ù)和選項:
- setAnimationStartDate:
- setAnimationDelay:
- setAnimationDuration:
- setAnimationCurve:
- setAnimationRepeatCount:
- setAnimationRepeatAutoreverses:
- setAnimationDelegate:
- setAnimationWillStartSelector:
- setAnimationDidStopSelector:
- setAnimationBeginsFromCurrentState:
注意: 如果不是為了支持很舊的設備, 則推薦使用下面的 lambda (block based method) 來實現(xiàn)動畫效果, 雖然 begin/commit 還能夠使用, 按照官方的說法, 對新系統(tǒng)來說是不推薦的了。
使用 lambda (block based method) 做動畫
在 iOS 4.0 以后, 引入了代碼塊 (code block) 的概念, 可以使用代碼塊來初始化動畫, 這也是在 iOS 4.0 之后蘋果推薦的做法, iOS SDK 提供的 API 如下:
- animateWithDuration:animations:
- animateWithDuration:animations:completion:
- animateWithDuration:delay:options:animations:completion:
而在 Xamarin.iOS (MonoTouch) 平臺下, 這些方法被綁定為下列方法:
- 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)
還是切換視圖的動畫, 如果用 objective-c 的代碼塊來實現(xiàn), 則應該是這樣子的:
[UIView animateWithDuration:1.0 animations:^{ self.firstView.alpha = 0.0; self.secondView.alpha = 1.0; }];
如果用 C# 來實現(xiàn)的話, 應該是這樣:
UIView.Animate(1.0, () => { this.FirstView.Alpha = 0.0f; this.SecondView.Alpha = 1.0f; });
這樣就實現(xià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]; }];
對應的 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 ); } );
嵌套動畫
iOS 支持嵌套的動畫, 也就是說在一個動畫代碼段中, 可以再開始另外一個動畫代碼段, 而不必等當前動畫完成, 嵌套的動畫會同時開始運行, 默認繼承原來動畫的延時、 時間長度、 加速曲線等, 不過這些選項也能被覆蓋。 例如:
[UIView animateWithDuration:1.0 delay:1.0 options:UIViewAnimationOptionCurveEaseOut animations:^{ self.firstView.alpha = 0.0f; // 這里開始一個新的動畫 [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 ];
對應的 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 );
對于使用 Begin/Commit 方法的動畫, 也可以嵌套調(diào)用 Begin/Commit 方法來實現(xiàn)嵌套的動畫, 例如:
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# 代碼對應的 ObjC 代碼很簡單, 就不寫出來了。
實現(xiàn)動畫的自動翻轉(zhuǎn)
當創(chuàng)建自動翻轉(zhuǎn)指定次數(shù)的動畫時, 考慮將重復次數(shù)設置為非整數(shù)值。 因為對于自動翻轉(zhuǎn)的動畫來說, 每次循環(huán)都是從原始值變化到目標值再變化回原始值, 如果希望動畫結(jié)束之后停留在目標值, 需要將重復次數(shù)設置加上 0.5 , 否則, 動畫回慢慢變回原始值, 再迅速變化到目標值, 這可能不是原來期望的動畫效果。
創(chuàng)建視圖切換動畫
視圖切換動畫可以減少修改可視化樹時引起的界面上的突變, iOS 系統(tǒng)中大量使用了視圖切換動畫, 視圖切換動畫主要有下面兩種場景:
- 修改子視圖
- 替換子視圖
注意: 不要把視圖切換和視圖控制器的切換混淆(顯示一個模式對話框、將視圖控制器推入導航堆棧等), 視圖切換改變的僅僅是視圖的可視化樹, 視圖控制器是不變的, 更多信息可以參考iOS視圖控制器編程指南。
修改子視圖
可以修改子視圖的可見性用來表示當前視圖的不同的狀態(tài), 看下面的兩個視圖切換的例子,在 iOS 4.0 之前, 需要將視圖切換動畫添加到 Begin/Commit 動畫之間, 代碼如下:
在 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];
這里只有動畫部分的代碼, 動畫完成之后請參考 setAnimationDelegate: 方法設置并實現(xiàn) UIAnimationDelegate 。
替換子視圖
要進行子視圖的替換, 需要用到 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; } } ];
鏈接多個動畫
有了上面的知識, 鏈接多個動畫就非常簡單了:
- 對于 lambda 或 block-based 方法的動畫, 使用 complete 回調(diào)函數(shù)即可;
- 對于 Begin/Commit 方法的動畫, 需要實現(xiàn)一個 UIAnimationDelegate , 然后調(diào)用 setAnimationDelegate 方法設置 Delegate 即可。
以上就是詳解 iOS 系統(tǒng)中的視圖動畫的詳細內(nèi)容,更多關于iOS 視圖動畫的資料請關注腳本之家其它相關文章!
相關文章
詳解iOS如何讓Lottie使用網(wǎng)絡資源做動畫的實現(xiàn)
這篇文章主要為大家介紹了iOS如何讓Lottie使用網(wǎng)絡資源做動畫實現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-02-02