當你開啟裝有iOS7以上的iPhone主屏,預設的背景是一幅藍色的星空圖片。當上下左右翻轉iPhone時,有趣的效果將會出現,星空背景也會沿著各個方向發生位移,這與主屏上的各個App Icon形成了一種獨特的視差效果。
這不是iOS系統本身獨有的。在iOS7之前,這種效果需要陀螺儀相關API的支援,實現起來也比較複雜。而在iOS7以後,系統提供了這樣的API,大大簡化了實現方案。
0. UIMotionEffect
在iOS7以上的的API中,有一個UIMotionEffect的類。通過它,我們也可以在自己開發的App當中實現本文開頭提到的效果。
我們來看一下UIMotionEffect:
1 2 3 |
NS_CLASS_AVAILABLE_IOS(7_0) @interface UIMotionEffect : NSObject <NSCopying, NSCoding> - (NSDictionary *)keyPathsAndRelativeValuesForViewerOffset:(UIOffset)viewerOffset; @end |
從標頭檔案的宣告來看,UIMotionEffect非常簡單,直接繼承自NSObject,支援了NSCopying和NSCoding protocol。同時,就像剛剛提到的,他是iOS7之後才有的類。
除此之外,只提供了一個可供override的方法。這個方法的輸入引數只有一個,觀察者角度的偏移。而這個方法的輸出則是一個靈活的NSDictionary物件,裡面包含了最終影響視差效果的各項屬性和對應的值。
在同一個標頭檔案中,還有一個UIInterpolatingMotionEffect類的宣告。
1. UIInterpolatingMotionEffect
UIInterpolatingMotionEffect是UIMotionEffect的子類,雖然擴充套件也不復雜,提供的方法也很簡單,但在很多場景下可以比較直接和方便的滿足我們的需求。
它有4個property:
- keyPath,左右翻轉螢幕將要影響到的屬性,比如center.x。
- type(UIInterpolatingMotionEffectType型別),觀察者視角,也就是螢幕傾斜的方式,目前區分水平和垂直兩種方式。
- minimumRelativeValue和maximumRelativeValue,keyPath對應的值的變化範圍,注意這個是id型別。min對應最小的offset,max對應最大的offset。
以本文開頭的效果為例,我們可以在某個controller對特定的view實現類似效果:
1 2 3 4 |
UIInterpolatingMotionEffect * xEffect = [[UIInterpolatingMotionEffect alloc] initWithKeyPath:@"center.x" type:UIInterpolatingMotionEffectTypeTiltAlongHorizontalAxis]; xEffect.minimumRelativeValue = [NSNumber numberWithFloat:-40.0]; xEffect.maximumRelativeValue = [NSNumber numberWithFloat:40.0]; [targetView addMotionEffect:xEffect]; |
當然,這只是x軸的,垂直方向同理。
怎麼樣?是不是很簡單?
2. 自定義MotionEffect
由於目前iOS對MotionEffect的支援還比較簡單,通過UIInterpolatingMotionEffect我們基本上可以實現大部分效果。
當然,如果我們比較任性,也可以通過繼承UIMotionEffect,自定義自己的效果。
比如說,當水平方向發生偏移的時候,我們讓targetView上下移動:
1 2 3 4 5 6 |
- (NSDictionary *)keyPathsAndRelativeValuesForViewerOffset:(UIOffset)viewerOffset { CGFloat originalOffset = viewerOffset.horizontal ; CGFloat targetOffset = 512 * originalOffset; return @{@"center.y": @(targetOffset)}; } |
如上,我們在繼承UIMotionEffect的子類中實現這樣一個方法就完成了。夠任性!
當然,UIMotionEffect不僅僅能夠支援本文提到的各種位移,這裡只是簡要的一個介紹。只要是targetView支援的動畫屬性,都可以做出效果來。
UIMotionEffect是iOS7才有的東西,雖然目前很多App還要考慮支援iOS的6.0、5.0、甚至4.3,但隨著目前iOS7和iOS8的使用者比例逐步擴大,甚至達到90%,iOS7的效果一定在不久的將來就可以被廣泛使用。