- (void)statusBarOrientationChange:(NSNotification *)notification { WClassAndFunctionName; UIInterfaceOrientation oriention = [UIApplication sharedApplication].statusBarOrientation; [self adaptUIBaseOnOriention:oriention]; }
一般情況下,關於屏幕旋轉的適配用view自帶的autoresizingmask屬性就能輕松適配寬度以及邊距,而且從iOS6到iOS8通吃。不過,前提是“一般情況下”。當你需要在橫屏與豎屏狀態下讓你封裝的view有不同的布局,那autoresizingMask屬性就顯得力不重新了。這也是本文要解決的主要問題。
顯然,檢測視圖旋轉事件是必須要做的。一般我們封裝一個自定義控件,總是希望調用者可以輕松的調用它,因此檢測視圖旋轉也應該在控件內做。
開始檢測視圖旋轉。
在init方法中注冊通知
- (void)registerListeningDeviceOriention { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(statusBarOrientationChange:) name:UIApplicationDidChangeStatusBarOrientationNotification object:nil]; }
一旦屏幕產生旋轉,則調用statusBarOrientionChange:方法。比如:
- (void)statusBarOrientationChange:(NSNotification *)notification { WClassAndFunctionName; UIInterfaceOrientation oriention = [UIApplication sharedApplication].statusBarOrientation; [self adaptUIBaseOnOriention:oriention];//比如改變self.frame }
然而,事情並不是那么順利跟想當然的!當你滿懷信心地在adaptUIBaseOnOriention方法中根據oriention做布局后會發現,iOS8跑出來的效果很完美,而非iOS8版本卻亂七八糟。很多時候自定義view(以下簡稱superview)的subviews的布局要依賴於superview的size。所以一旦superview的frame沒有適配好,那看起來就亂七八糟了!為什么會出現上述差異呢?根本原因是statusBarOrientationChange的觸發時機依賴於ios版本。打log后發現,iOS8及以上的版本,statusBarOrientationChange在旋轉結束后調用;在iOS8以下的版本,statusBarOrientationChange在旋轉前調用。而如果你在statusBarOrientationChange方法中想當然地去讀取當前的設備高度跟寬度,那必然產生差異!
總體思路是沒錯的,下一步就是在statusBarOrientationChange里面對當前的設備方向以及系統版本進行判斷,這樣才能取到真正的設備高度跟寬度,真正的設備高度寬度對於布局是至關重要的!
CGFloat windowWidth = kDeviceWindowWidth4Panel;//iOS8不用更改 CGFloat windowHeight = kDeviceWindowHeight4Panel; if (!IsIOS8orAbove) { windowWidth = (!kIsDeviceLandscape) ? kDeviceWindowWidth4Panel:kDeviceWindowHeight; windowHeight = (!kIsDeviceLandscape) ? kDeviceWindowHeight4Panel:(kDeviceWindowWidth - (IsIOS7orAbove ? 0 : kSystemStatusBarHeight)); }
其實,本質上可以簡述為:iOS8上windowSize取的是當前時刻的windowSize值,因此可以直接賦值;iOS8以下的windowSize取得是下一時刻旋轉后的值,相當於預判了。
最后一點需要注意的地方是,如果你需要在statusBarOrientationChange方法中手動改變superview的frame,那請把init方法中的autoresizingMask屬性全部注釋掉,因為兩者是沖突的,尤其是在iOS8以下。因為在iOS8以下本質上是在旋轉之前就將所有的subviews的布局更新為旋轉后的狀態了,這樣翻轉過去就能正常顯示。如果你加了autoresizingMask屬性,那系統會根據旋轉前最后一刻的狀態來適配,這樣旋轉后就群魔亂舞了。