iOS 7:用程式碼解決檢視控制器的View整體上移問題
如果你準備將你的老的 iOS 6 app 遷移到 iOS 7 上,那麼你必須注意了。當你的老的 app 在 iOS 7 裝置上執行時,所有ViewController 的檢視都整體上移了,因為 iOS 7 把整個螢幕高度(包括狀態列和導航欄)都作為了檢視控制器的有效高度。於是你的檢視上移了,並和上層的狀態列交疊在一起。
你當然可以在 Xcode 中修改每個 View,將他們下移20個畫素(狀態列高度)或者64個畫素(狀態列+導航欄高度)。
但是蘋果顯然已經考慮到這個問題,他們在 iOS 7 SDK 中為 ViewController 提供了一個 edgesForExtendedLayout 新屬性。如果你將這個屬性設定為UIRectEdgeNone,則 viewController 的所有子檢視都會自動調整,這樣在 iOS 7 下看到的效果和 iOS 6 完全一樣。
為了方便,你可以為 UIViewController 擴充套件一個子類,並覆蓋它的 viewDidLoad 方法:
@implementation DerivedViewController
- (void)viewDidLoad
{
[superviewDidLoad];
if ([selfrespondsToSelector:@selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
}
@end
然後你以後所有的 ViewController 都從這個 DerivedViewController 類繼承。
但不幸的是,我們的程式仍然有大量 iOS<7 的使用者 ,我們無法立即拋棄對 iOS 6 的支援。無論 edgesForExtendedLayout 還是UIRectEdgeNone,都只能在 iOS7 下有效。對於 iOS 6,我將以上程式碼修改為:
- (void)viewDidLoad
{
[superviewDidLoad];
#if__IPHONE_OS_VERSION_MAX_ALLOWED >= 70000
if ([selfrespondsToSelector:@selector(edgesForExtendedLayout)])
self.edgesForExtendedLayout = UIRectEdgeNone;
#else
float barHeight =0;
if (!isIPad()&& ![[UIApplication sharedApplication] isStatusBarHidden]) {
barHeight+=([[UIApplication sharedApplication]statusBarFrame]).size.height;
}
if(self.navigationController &&!self.navigationController.navigationBarHidden) {
barHeight+=self.navigationController.navigationBar.frame.size.height;
}
for (UIView *viewin self.view.subviews) {
if ([view isKindOfClass:[UIScrollView class]]) {
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y +barHeight, view.frame.size.width, view.frame.size.height - barHeight);
} else {
view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y +barHeight, view.frame.size.width, view.frame.size.height);
}
}
#endif
}
通過巨集 __IPHONE_OS_VERSION_MAX_ALLOWED 判斷 deployment target 是否 >7.0。>7.0則使用新的 edgesForExtendedLayout API,負責使用比較笨的方法逐個下移 subviews,並自動根據狀態列/導航欄的可視狀態計算要移動的偏移量。
注:如果已升級至Xcode5,將導航控制器的 Top Bar 設定為一種“Opacque ...”(不透明)型別可解決此問題。